Ilan Chamovitz
Lógica de programação
Lógica de programação
03
Ilan Chamovitz
Lógica de programação
São Paulo Rede Internacional de Universidades Laureate 2015 05
© Copyright 2015 da Laureate. É permitida a reprodução total ou parcial, desde que sejam respeitados os direitos do Autor, conforme determinam a Lei n.º 9.610/98 (Lei do Direito Autoral) e a Constituição Federal, art. 5º, inc. XXVII e XXVIII, “a” e “b”. Dados Internacionais de Catalogação na Publicação (CIP) (Sistema de Bibliotecas da UNIFACS Universidade Salvador - Laureate International Universities)
Sumário Apresentação.................................................................................................................09
CAPÍTULO 1 – Introdução à Lógica de Programação..........................................................11 Introdução.....................................................................................................................11 1.1 Conceitos fundamentais.............................................................................................11 1.1.1 A lógica e o computador...................................................................................13 1.2 Algoritmo.................................................................................................................15 1.2.1 Algoritmo: problema, entrada e saída ................................................................17 1.2.2 Avaliação de Algoritmos...................................................................................18 1.3 Variáveis..................................................................................................................21 1.3.1 Variáveis e outros elementos que compõem linguagens de programação ...............28 1.3.2 Tipos de variáveis.............................................................................................29 Síntese...........................................................................................................................31 Referências Bibliográficas.................................................................................................32
CAPÍTULO 2 – Dados: Entrada e Saída.............................................................................35 Introdução.....................................................................................................................35 2.1 Tipos de dados.........................................................................................................35 2.1.1 A importância da definição do tipo de dado........................................................36 2.2 Entrada e saída de dados...........................................................................................39 2.2.1 A Importância da Entrada e Saída de Dados ......................................................40 2.2.2 Trabalhe mais a entrada de dados e evite problemas na saída...............................41 2.2.3 O acesso aos dados.........................................................................................42 2.3 Tipos de estruturas de dados......................................................................................43 2.3.1 Vetores............................................................................................................44 2.3.2 Matrizes..........................................................................................................45 2.3.3 Registros.........................................................................................................47 2.4 Listas, Filas e Pilhas...................................................................................................48 2.4.1 Listas..............................................................................................................49 07
2.4.2 Filas................................................................................................................50 2.4.3 Pilhas..............................................................................................................51 2.5 Árvores....................................................................................................................51 2.6 Grafos.....................................................................................................................52 Síntese...........................................................................................................................54 Referências Bibliográficas.................................................................................................55
CAPÍTULO 3 – Introdução à linguagem de programação.....................................................57 Introdução.....................................................................................................................57 3.1 Linguagem de máquina.............................................................................................58 3.1.1 Linguagens de programação: linguagem de máquina e de baixo nível ..................58 3.2 Linguagem de programação.......................................................................................59 3.2.1 Funções..........................................................................................................63 3.2.2 Bibliotecas.......................................................................................................65 3.2.3 Lógica, Linguagens de Programação e Internet....................................................65 3.2.4 A lógica do E e do OU.....................................................................................73 3.2.5 Dicas e máximas sobre problemas e a programação............................................74 Síntese...........................................................................................................................75 Referências Bibliográficas.................................................................................................76
CAPÍTULO 4 – Linguagem de programação: estruturas condicionais e de repetição...............77 Introdução.....................................................................................................................77 4.1 Estruturas condicionais..............................................................................................77 4.2 Estruturas de repetição..............................................................................................87 4.3 Solução de problemas...............................................................................................94 Síntese...........................................................................................................................98 Referências Bibliográficas.................................................................................................99 Minicurrículo do autor...................................................................................................101
08 Laureate- International Universities
Apresentação Apresentação Seja bem-vindo à disciplina à disciplina Lógica de Programação! Se você está na área de Engenharia, provavelmente já utilizou algum conceito relacionado com a Lógica. Você seria capaz de pensar em pelo menos duas situações nas quais utilizou a lógica? Certamente que sim. A lógica faz parte de nossa rotina diária. Afinal, ela ajuda a resolver problemas. A lógica é utilizada para lidar com informação, prever cenários, sugerir mudanças e até programar máquinas! Esta disciplina não visa o desenvolvimento de programas e sistemas, mas fornecerá as bases fundamentais para que você possa compreender como funcionam tais sistemas e programas e, possivelmente, aprender linguagens de programação com muito mais facilidade! Enfim, seguiremos uma lógica (Sim! Aqui também!). Como verão adiante, o Engenheiro de Produção precisa pensar em recurso e como serão utilizados; logo, ele precisa da lógica. O Engenhero Civil sabe, também, que uma construção precisa contar com estoques em determinado local, em um determinado momento. Ora, poderíamos citar aqui outras áreas das engenharias e conseguirímos muitos exemplos. E, se precisássemos, poderíamos enumerar dezenas ou centenas de programas de computador que apoiam as atividades nas engenharias. Então, fica clara a importância de se conhecer os elementos principais da lógica de programação. Para que esta disciplina fosse organizada de forma didática, utilizaremos muitos exemplos. Lembre-se: o objetivo é o aprendizado e o uso da Lógica para facilitar o entendimento de sistemas e de linguagens de programação. Então, para que a disciplina fique ainda mais interessante, ela foi dividida em quatro partes: A primeira introduz a Lógica de Programação. Serão apresentados conceitos fundamentais e elementos principais utilizados na lógica de programação. Possivelmente você já ouviu falar em algoritmos e variáveis. Se já ouviu, poderá realizar uma releitura de seus conhecimentos. Se não conhece, você será introduzido a um conjunto de conceitos relacionados a estes dois temas. A segunda parte abordará conceitos relacionados a “Dados”, principal insumo que é processado e computado por programas de computador. Sabemos que a quantidade de problemas gerados por falta de atenção ao dado é muito grande, nas empresas. Nesta unidade você conhecerá, de uma forma mais didática, como os programas utilizam os dados e de que forma podemos melhorar o tratamento dos dados. Na terceira parte da disciplina haverá uma introdução às linguagens de programação, abordando linguagem de máquina e outras linguagens de mais alto nível. Você conhecerá um pouco mais sobre alguns aspectos das linguagens em geral. Ou seja, não vamos nos fixar em uma linguagem, mas abriremos o nosso campo de visão para perceber similaridades e possíveis diferenças nas linguagens, em sua estrutura e tratamento. A quarta e última parte desta disciplina apresentará estruturas condicionais e estruturas de repetição. Afinal, pense: “Se você está cursando esta disciplina” (esta é uma expressão de condição), LOGICAMENTE (ou seja, pela lógica) você deverá esforçar-se para aprender os conceitos e realizar uma excelente prova! (esta é uma expressão resultante da expressão de condição).
09
Agora perceba esta outra sentença: ENQUANTO não obter, nesta disciplina, o valor mínimo que evidencie o seu conhecimento, o acesso à matrícula em outras disciplinas será negado. (Esta é uma expressão que resulta em uma repetição enquanto houver a condição – conseguir valor mínimo). Como pode perceber, usamos a lógica e nos programamos para criar regras, seguir comandos, mesmo sem sabermos. A lógica de programação está presente em nossa vida e este é o melhor momento para você entendê-la. Então... vamos em frente!
10 Laureate- International Universities
Capítulo 1 Introdução à Lógica de Programação
Introdução Lógica é definida como o “modo de raciocinar”. Segundo a definição do dicionário Aurélio (1986), é coerência de raciocínio, ou um modo de raciocinar peculiar a alguém ou a um grupo. Também pode ser conceituada como uma sequência coerente, regular e necessária de acontecimentos ou de coisas. A história da lógica inicia na Grécia, com os três grandes filósofos Sócrates, Platão e Aristóteles, buscando desenvolver o conhecimento por meio da investigação sistemática, científica, através da lógica. Bem mais adiante, a lógica moderna surge com o trabalho “Investigation of the Laws of Thougt” que foi apresentado por George Boole (1815-1864). Mas você sabe o que isso tudo tem a ver com programação? Como utilizar a lógica para solucionar problemas do nosso cotidiano? A Ciência da Computação e a Informática utilizam a lógica de forma intensa, e você começará a compreender como isso ocorre ao iniciar o estudo desta disciplina. Vamos lá?
1.1 Conceitos fundamentais A computação pode nos ajudar a resolver problemas formais, que são problemas associados a um modelo lógico sobre um fenômeno. Observe a figura proposta pelo professor Francisco Chagas de Lima Júnior (2009):
Figura 1 - Esquema para resolução de problemas Fonte: Lima Júnior, 2009.
11
Lógica de programação
A figura apresenta um esquema para a resolução de problemas reais utilizando a lógica e os formalismos para modelar e construir modelos computacionais que, após serem implementados, resolvem ou auxiliam na resolução do problema. A partir do problema real, é construído o modelo simbólico, utilizado na modelagem
VOCÊ O CONHECE? Alan Turing (1912-1954) foi um grande pesquisador da lógica de computadores. Ele buscava compreender o que a computação poderia realmente fazer, ou seja, estava interessado em problemas formais e práticos que poderiam ser resolvidos através de computadores. Durante seus estudos, ele desenvolveu uma máquina, a Turing Universal Machine, que calculava números e funções de acordo com instruções apropriadas. Após a Segunda Guerra Mundial, Turing trabalhou no projeto da Automatic Computing Engine (ACE). Em 1948, ele foi nomeado Leitor no Departamento de Matemática em Manchester. Logo depois, ele se tornou vice-diretor do Laboratório de Computação da Universidade de Manchester e trabalhou em software para um dos primeiros computadores – o Manchester Ferranti Mark 1. Em 1952, Alan Turing voltou sua atenção para o campo então emergente da morfogênese, propondo uma nova hipótese para a formação de padrões em sistemas biológicos. Turing morreu em 7 de junho de 1954, com 41 anos. Ele é considerado o pai da computação moderna e inteligência artificial. Seu conceito de máquina de Turing ainda é uma das teorias mais amplamente examinadas de computação.
NÃO DEIXE DE VER... Assista ao filme O Jogo da Imitação (2015), com Benedict Cumberbatch e Keira Knightley, para saber mais sobre a história de Turing e sua importância para a computação.
A Lógica de Programação pode variar de acordo com os recursos das linguagens de programação e os seus paradigmas. Para Tuker (2008), um paradigma de programação é um padrão para a resolução de problemas relacionados ao determinado gênero de programas e linguagens. Assim, existem alguns padrões que podem ser utilizados para a solução de problemas. Tucker (2008) apresenta os paradigmas listados a seguir. 1. Programação orientada a objetos: um programa é uma coleção de objetos que interagem entre si, passando mensagens que transformam seu estado. 2. Programação Funcional: modela um problema computacional como uma coleção de funções matemáticas, cada uma com um domínio e um resultado. As funções interagem entre si usando composição funcional, condições e recursão. 3. Programação Lógica: modela um problema declarando qual o resultado desejado, sem focar em como ele deve chegar lá. Nesse caso, as linguagens de programação fundamentam-se em regras. 4. Programação orientada a eventos: utiliza sensores que “percebem” a execução de eventos e determinados comportamentos do usuário. Por exemplo, cliques de mouse e a digitação de um texto em uma caixa de texto. 12 Laureate- International Universities
5. Programação imperativa: este paradigma é bem antigo. O programa e as suas variáveis são armazenados juntos. O programa aloca espaços para variáveis e executa ações por meio de comandos. 6. Programação orientada a aspectos: separa o código de acordo com a sua importância na aplicação. 7. Programação concorrente: este paradigma associa-se com os da programação orientada a objetos, funcional, lógica e imperativa. Caracteriza-se pela concorrência de acesso a elementos que compartilham informação em intervalos de tempo. 8. Programação reflexiva: trata da capacidade de um programa para criar e executar comandos em tempo de e execução. Conhecida também como metaprogramação.
Esses paradigmas determinam a abordagem aplicada pelas linguagens. Nesta disciplina, não focaremos um paradigma único – abordaremos a lógica de programação de forma genérica. Parte de muitas linguagens de programação já inclui uma série de funções ou de bibliotecas com trechos de programas que executam ações já predefinidas. Dessa forma, muitas vezes os programadores só precisam saber valores a serem passados para aquele elemento e qual será o resultado esperado, a ser recebido, transferido ou armazenado em algum local.
1.1.1 A lógica e o computador Você viu que a lógica de programação está intrinsicamente ligada ao computador. Mas você sabe por que ele tem esse nome? Essa é uma pergunta muito fácil de ser respondida. Computar tem origem no latim: computo, -are, que significa calcular, contar. E é isso que o computador faz: por meio da computação, ou seja, realizando contas e cálculos, ele transforma os dados. Um computador pode ser definido como uma máquina eletrônica que recebe dados através dos periféricos de entrada, processa esses dados realizando operações lógicas e aritméticas e transforma-os em outros dados que são enviados aos periféricos de saída ou, simplesmente, armazenados em algum dispositivo.
13
Lógica de programação
010101
Dados
Periféricos de entrada
Computador
Periféricos de saída
010101
Dados
Periféricos de entrada
Computador
Armazenamento
Figura 2 – Esquema de funcionamento do computador. Fonte: Chamovitz, 2015.
Para realizar esses procedimentos, um computador precisa ser programado. Essa programação envolve uma sequência de comandos, que deve seguir uma lógica: a lógica de programação. Ela é a base das linguagens de programação, compostas de um conjunto de comandos que, quando acionados, permitem realizar operações. A partir de agora, você estudará dois elementos fundamentais presentes nas linguagens de programação: os algoritmos e as variáveis. Sua compreensão é necessária para que haja o entendimento adequado da lógica de programação.
NÃO DEIXE DE LER... Como foi a evolução da lógica ao longo do tempo? Carlos Fontes apresenta a Breve História da Lógica, dividindo os diferentes períodos em três partes: Período Clássico, Período Moderno e Período Contemporâneo. Acesse e leia em: <http://afilosofia. no.sapo.pt/Hist.htm>
14 Laureate- International Universities
1.2 Algoritmo Para Binder e Direne (1999), Lógica de programação relaciona-se com a habilidade de agrupar adequadamente os comandos a fim de resultar num algoritmo. Mas o que é um algoritmo? Vamos explicar por meio de um exemplo prático do cotidiano. Imagine que você acaba de comprar uma impressora nova. Em relação à sua impressora atual, esse novo modelo oferece diversas vantagens: a impressão tem mais qualidade e você também ganhará tempo, pois a velocidade de impressão é maior. Outro benefício é que o novo equipamento permite dois tipos de conexão: com ou sem fio. Você terá de escolher como vai utilizá-lo. Ao colocar a impressora sobre a sua mesa de trabalho, ela não vai imprimir imediatamente. Existem passos a serem seguidos por você, até que ela esteja preparada para imprimir. Um algoritmo pode ser definido como:
• um passo a passo descrevendo ações para a solução de um problema; • uma
sequência detalhada de ações que devem ser executadas para se cumprir determinada tarefa.
Em nosso exemplo, se a impressora não foi ligada, ela não irá funcionar. Da mesma forma, se não estiver abastecida com papel, não será possível imprimir relatórios. Antes de enviar o seu documento para a impressão, algumas ações precisam ser realizadas. Um algoritmo precisa ser desenvolvido. Você pode, então, iniciar a compreensão do que são algoritmos pensando em situações práticas do seu cotidiano. Um exemplo clássico é o da receita culinária. Veja o exemplo a seguir e note que existem três partes: uma introdução com o principal resultado oferecido pela receita (rendimento), os ingredientes (elementos necessários, incluindo insumos e utensílios) e, por fim, os procedimentos. Lembre-se bem desses três elementos.
Rendimento: 15 unidades grandes Esta receita de massa de pastel é um combinado de dicas de pasteleiros de feira, de pastelarias de rua e de professores de gastronomia do Senac e da Anhembi Morumbi. A massa presta-se ao recheio que você quiser – da carne à feijoada do almoço de ontem e até ao vento. Para não ter erro na hora do preparo, basta seguir os truques compilados aqui.
Ingredientes
• 3
xícaras de farinha de trigo (separar pelo menos uma xícara a mais para trabalhar a massa e dar o ponto)
• 1 copo e meio de água (400 ml) • 2 colheres (sopa) de óleo (opcional) • 1 colher (sopa) de sal • 1 dose de pinga (50 ml)
15
Lógica de programação
Preparo 1. Misture bem a farinha com o sal. 2. Abra um buraco no meio da farinha e jogue, aos poucos, a água, incorporando-a à farinha com as mãos num bowl fundo ou numa mesa lisa. Se quiser dar uma liga a mais na massa, adicione as colheres de óleo. 3. Acrescente a cachaça e continue misturando bem a massa. 4. Sove a massa em uma superfície lisa, polvilhada de farinha, até que fique homogênea e pare de grudar nas mãos. 5. Deixe a massa descansar por 15 minutos coberta com pano úmido ou plástico filme. 6. Abra a massa com a ajuda de cilindros – é mais fácil – até a espessura mais fina que conseguir, sem que a massa quebre; se não tiver a máquina, um rolo faz também a função. 7. Corte a massa já aberta com uma faca com até 30 cm de altura e 10 cm de largura, para ficar do tamanho de um pastel de feira. 8. Recheie a massa, ocupando no máximo metade do espaço, dobre a massa e feche as bordas com a ajuda de um garfo. 9. Depois de montar os pastéis, leve o quanto antes ao óleo quente para fritar. (ORESTEIN, 2014). O segundo exemplo também é clássico e mostra uma sequência de procedimentos para se chegar a algum ponto turístico. Recuperamos, assim, parte da descrição para chegar a Trindade, no litoral do Rio de Janeiro. IMPORTANTE: não é permitida a entrada de vans e ônibus de turismo em Trindade. Para a chegada de grupos, siga os procedimentos da Prefeitura de Paraty em: <http://www. paraty.com.br/autorizacao_onibus.asp>. Seu veículo deverá ficar estacionado no pátio, ao lado da Rodoviária de Paraty e, para ir até Trindade, o grupo deverá se locomover de ônibus de linha Colitur. DE CARRO: Do trevo de Paraty até o trevo do Patrimônio, onde se inicia a estrada que leva a Trindade, a distância é de 16 km. A estrada para Trindade atravessa o morro do Deus-me-livre, assim chamado pois antigamente era muito difícil atravéssá-lo em dias de chuva. Hoje a estrada está asfaltada. Logo no início da estrada para Trindade está a sede da Associação Cairuçu, com seu posto de informações turísticas e, ao lado, há um posto policial. Após a primeira subida, há uma bifurcação: Siga à direita, para Trindade (à esquerda segue-se para o condomínio de Laranjeiras). A estrada é sinuosa e rodeada de verde. Aos poucos aparecem belas imagens do mar. A primeira praia que aparece é a Praia do Cepilho, a preferida dos surfistas. Atravessando o pequeno riacho e seguindo em frente chega-se à Vila da Trindade. (PORTAL DE TRINDADE, 2015)
16 Laureate- International Universities
Observe que existe uma sequência de comandos. Perceba, também, que após a primeira subida (penúltimo parágrafo), existe uma bifurcação, e o “algoritmo” considera a possibilidade de se ir para a direita ou para a esquerda, mesmo que o caminho desejado seja à direita. O algoritmo também oferece um certo nível de detalhe. O nosso exemplo poderia ser ainda mais minucioso, indicando, por exemplo, algum ponto de referência a cada 200 metros.
1.2.1 Algoritmo: problema, entrada e saída Na computação, um algoritmo é qualquer procedimento computacional que recebe como entrada um valor (ou conjunto de valores) e produz como saída outro valor (ou um conjunto de valores). É uma sequência de passos computacionais que transforma entrada em saída. Esses três elementos – problema, entrada e saída – são fundamentais para o entendimento dos algoritmos. Por exemplo:
• problema: encontrar o número par em um vetor com n elementos; • entrada: vetor com n elementos; • saída: o elemento par com o maior valor. A escrita de um algoritmo geralmente segue o seguinte formato: INICIO Primeira parte PROCEDA Segunda parte FIM
NÓS QUEREMOS SABER! Por que utilizamos essa linguagem de algoritmos ao invés da linguagem coloquial? Porque a linguagem coloquial pode dar margem a erros. Veja a frase a seguir: “abaixo de 25 anos, a pessoa é jovem, acima, não é jovem”. Sem percebermos, esquecemos de indicar como classificar a pessoa com exatos 25 anos. Por isso, é importante uma certa formalidade. Entretanto, enquanto estamos pensando na lógica, e não na implementação, não há a necessidade de todo o formalismo de uma linguagem de programação.
Você poderá encontrar algoritmos em Português Estruturado (conhecido como Portugol), Inglês Estruturado ou, ainda, em um código de linguagem, como Java ou C++, por exemplo. Veja os dois exemplos a seguir, utilizando um algoritmo escrito em inglês. Eles apresentam linhas com uma linguagem que será estudada mais adiante. O mais importante neste momento é você perceber que existe uma linha no início (Begin), uma no final (END) e linhas intermediárias.
17
Lógica de programação
Algoritmo
Explicação
Procedure exemplo1(var a:vetor);
Nome do procedimento (declara variável a como sendo um vetor.
Begin
Início
read(x);
Leia a variável x de entrada
a[1]:=x;
Atribui o valor lido para a primeira posição do vetor
End;
FIM do procedimento Quadro 1 - Procedimento do exemplo 1. Fonte: Elaborado pelo autor, 2015.
Agora, para ilustrar, veja outro exemplo de procedimento, um pouco mais complexo.
Algoritmo
Explicação
Procedure exemplo2(var a:vetor);
Nome do procedimento (declara variável a como sendo um vetor. Algumas linguagens permitem)
Begin
Início
read(x);
Leia a variável x de entrada
if (x<0)
Se x for um negativo
a[1]:= 0;
A primeira posição do vetor será zero
else if (x<5)
Senão… se x for maior ou igual a 0 e menor que 5, a
a[1]:= 1;
primeira posição do vetor será 1
else for i:= 1 to n do
Do contrário (se for igual ou maior que 5), para i variando
begin
de 1 até n faça:
a[i]:= i+1;
Passa para a próxima posição do vetor.
end;
Fim do variando
End;
FIM do procedimento Quadro 2 - Procedimento do exemplo 2. Fonte: Elaborado pelo autor, 2015.
1.2.2 Avaliação de Algoritmos Os algoritmos são fundamentais para que possamos desenvolver programas de computador que podem facilitar o entendimento das linguagens de programação. Os algoritmos podem ser mais ou menos detalhados. Esse detalhamento pode facilitar o entendimento da sequência de passos necessários para se conseguir realizar determinada tarefa. 18 Laureate- International Universities
A análise de algoritmos pode almejar três objetivos: 1. avaliar um algoritmo para verificar se ele é eficiente; 2. verificar se um algoritmo é correto ou incorreto; 3. comparar vários algoritmos para ver qual é o mais adequado ou eficiente. Para avaliar um algoritmo, é comum implementá-lo em um computador e executá-lo com várias alternativas do problema. Deve-se escolher então um ou mais critérios que definirão se o algoritmo é eficiente. Pode-se considerar o tempo de execução ou a facilidade de entendimento do código, por exemplo. Esse tipo de avaliação é conhecido como avaliação empírica. Pode-se analisar também a complexidade de um algoritmo, algo que pode ser feito de diversas formas. Por exemplo, pode-se considerar a quantidade de entradas que ele recebe ou, ainda, o número de loops (estruturas do tipo “Faça Enquanto”, que serão apresentadas adiante), o número de atribuições de valores a variáveis, se existem, ou não loops aninhados (um loop dentro de outro loop), entre outras características. O comportamento de um algoritmo para grandes volumes de dados de entrada é conhecido como comportamento assintótico. Um recurso interessante para analisar um algoritmo é criar um fluxograma. Xavier (2015) apresenta definições para fluxogramas e pseudocódigos: “Fluxogramas e pseudocódigos são formas simples e diagramadas de código pronto. O objetivo de um fluxograma ou pseudocódigo é mostrar de antemão a lógica usada na solução de um problema (algoritmo).” (XAVIER, 2015, s/p). Para o autor, não existe um padrão definido para o pseudocódigo, de forma que é válido escrevê-lo de qualquer maneira, pois o importante é transmitir as principais ideias que permitam pensar em uma lógica que será aplicada na programação. Entretanto, algumas convenções surgiram e podem até ser utilizadas por alguns programas que convertem um pseudocódigo que utilize essas convenções em um programa, diretamente. Fluxogramas são representações gráficas e que visam o mesmo objetivo do pseudocódigo: transmitir as principais ideias da lógica que será aplicada na programação. A diferença entre fluxogramas e pseudocódigo está na representação visual existente nos fluxogramas. Veja o exemplo oferecido por Xavier (2015), com um pseudocódigo e um fluxograma na figura a seguir.
pseudocódigo1 INÍCIO entrada de dado : grava em VAR1 verificar var1 : letra ? verdade : imprimir dado -> “você digitou uma letra” falso : imprimir dado -> “você digitou um número” FIM pseudocódigo2
Início VAR1
INÍCIO : procedimento VARIÁVEIS var1 var1 <- entrada de dados : TECLADO SE (VAR1 É letra) então imprimir dado:MONITOR -> “Você digitou uma letra” caso contrário imprimir dado:MONITOR -> “Você digitou um número” FIM: procedimento
não
você digitou um número
VAR1 = letra? sim
Fim você digitou uma letra
Figura 3 – Pseudocódigo e Fluxograma. Fonte: Xavier, 2015.
19
Lógica de programação
Agora, veja o algoritmo seguinte.
início Trazer lâmpadas novas Pegar a escada Posicionar a escada
1. Trazer lâmpadas novas 2. Pegar a escada 3. Posicionar a escada 4. Acionar o interruptor 5. Se a lâmpada não acender, então: 5. 1 subir na escada 5. 2 retirar a lâmpada queimada 5. 3 colocar a lâmpada nova 5. 4 descer da escada
Acionar o interruptor V
Acendeu? F subir na escada
retirar a lâmpada queimada colocar a lâmpada nova fim
Figura 4 - Fluxo e algoritmo para trocar uma lâmpada. Fonte: Elaborada pelo autor, 2015.
Vamos analisar o algoritmo e o fluxograma criado. Estude e compare os dois, por 1 ou 2 minutos. Você percebe alguma inconsistência? Anote ou registre mentalmente que inconsistências encontrou. Posteriormente, nesta unidade, elas serão indicadas. Agora, olhando apenas o fluxograma, você consegue identificar para que ele serve? Sua resposta deve ter sido positiva e encontrá-la foi bem simples, pois a tarefa – trocar uma lâmpada – pode ser realizada facilmente por pessoas, certo? Agora, imagine que você vai programar uma máquina, um robô, que vai executar essa mesma tarefa. Suponha que ele pode subir na escada, como um ser humano. Nesse caso, o algoritmo anterio não será suficiente! Lembre-se de que podemos escrever algoritmos com mais ou com menos detalhes. Por exemplo, uma pessoa alta subirá somente dois degraus, enquanto alguém com altura menor terá de subir três ou quatro. Outro aspecto que você deve observar é que o algoritmo não especifica o que significa retirar a lâmpada queimada: envolver a lâmpada, segurá-la e rodar no sentido anti-horário até que ela se solte. Além disso, antes de trocar a lâmpada, talvez seja interessante vestir uma luva ou testar a sua temperatura, pois poderá estar muito quente. Uma vez que você já tenha percebido que existem várias possibilidades para escrever um algoritmo para resolver um problema, veja as inconsistências entre o fluxograma e a descrição do algoritmo. 1. O fluxo não apresenta a ação de descer da escada.
20 Laureate- International Universities
2. Se o fluxo informa as tarefas iniciais – trazer lâmpadas novas ─, deveria indicar o que fazer com as lâmpadas queimadas, para manter a consistência. E a descrição deveria acompanhar essas mudanças. 3. Da mesma forma que o item anterior, guardar a escada que buscou deveria constar no algoritmo. 4. Após trocar a lâmpada, seria preciso repetir a ação de acionar o interruptor e testar se está funcionando após a troca. Caso a luz não acenda, deve-se seguir o fluxo para a troca novamente. 5. Perceba que houve três ações antes de se acionar o interruptor. Se a lâmpada acender, essas ações foram inúteis. Note, então, que escrever um algoritmo pode ser fácil. Mas torná-lo útil e eficiente é um pouco mais complexo, porque exige experiência, atenção aos detalhes e domínio da lógica.
NÃO DEIXE DE LER... Um bom livro para começar a entender o assunto é Lógica De Programação (FORBELLONE, Eberspächer, 2005), por não exigir conhecimentos prévios em informática. O texto introduz o leitor no universo da lógica aplicada à programação de computadores de maneira independente de características de máquina e utiliza uma pseudolinguagem intencionalmente próxima às linguagens de programação comumente adotadas como primeira linguagem, para facilitar a posterior tradução e a implementação prática.
1.3 Variáveis Para realizar cálculos, os computadores utilizam algumas áreas de memória que servem para armazenar valores. O valor de uma variável pode ser alterado durante a execução do algoritmo. E esse valor pode assumir diversos tipos, que também podem ser modificados durante a execução.
NÓS QUEREMOS SABER! Quando e por que definimos variáveis? Deve-se definir as variáveis sempre, para que sejam identificadas e processadas. Ou seja, quando definimos a variável, alocamos um espaço na memória do computador para armazenar o valor que vamos atribuir. Ao definir a variável, informamos o tipo e o tamanho do dado que será armazenado e processado.
Os nomes das variáveis devem representar o significado do valor armazenado. Algumas regras variam de acordo com as linguagens, mas, em geral:
• o primeiro caractere deverá ser sempre alfabético; • não se utilizam espaços em branco no nome das variáveis; 21
Lógica de programação
• pode-se utilizar o sublinhado no lugar do espaço; • não devem ser usados caracteres especiais; • em
algumas linguagens, há a limitação de quantidade de caracteres para o nome de variáveis.
Além disso, lembre-se de que existem alguns nomes que já fazem parte do vocabulário das linguagens e deverão ser alterados caso implemente-se o algoritmo em uma linguagem. Por exemplo: “max” pode indicar uma variável que vai armazenar um valor máximo de uma lista de valores. Porém, “max” também pode ser reconhecido em uma linguagem como o nome de uma função. Logo, esse nome não seria aceito em um programa de computador e acusaria um erro. No algoritmo, nada será processado, mas fique atento para evitar problemas na implementação do algoritmo! Para declarar uma variável, informe o seu nome seguido pelo seu tipo. Observe os exemplos a seguir e perceba o erro, quando houver.
• Variável1: nome correto, mas não recomendável, pois não indica o conteúdo da variável. • custo total: nome incorreto, com espaço em branco. • custo_total: correto. • Comentario$: incorreto, pois usa símbolos especiais. • 1cliente: incorreto, pois iniciou-se com um número. • Numero 1º: incorreto, pois usa caracter especial após o “1” e ainda deixou espaço em branco.
Um exemplo da declaração e já com inicialização com um valor seria:
• comissão: do tipo inteiro; • comissao:=10 O exemplo anterior define comissão com valor 10 e informa que o tipo de dado armazenado deverá ser um inteiro. Se for atribuído um valor 10.99, será armazenado um inteiro. O valor poderá ser truncado e ficar com 10 ou o valor poderá ser arredondado e ficar com 11. Os principais tipos primitivos utilizados em grande parte das linguagens de programação são:
• inteiro: números inteiros maiores ou menores que 0 representados por 2 bytes, em uma faixa de valor que vai de -32768 até 32767. Exemplo: comissão:inteiro;
• real: conjunto dos números racionais, representado por 4 bytes. Exemplo: custo:real; • caracter: conjunto dos caracteres alfanuméricos, (números, letras, símbolos) representado
por apenas 1 byte. Exemplo: sexo:caractere, que pode assumir valores com apenas uma letra;
• cadeia
de caracteres: é um agregado de caracteres. Exemplo de uma cadeia com 30 caracteres atribuída à variável nome_fornecedor: nome_fornecedor:cadeia de caracteres
22 Laureate- International Universities
[30]. Pode-se encontrar, ao invés de cadeia de caracteres, o nome “string”;
• lógico: assume somente um valor entre verdadeiro (true, .t.) ou falso (false, .t.). Exemplo: gerente:verdadeiro.
A partir dos dados primitivos, podemos agregá-los e utilizar novos tipos de dados. Exemplos: cadeia de carateres, matriz e registro. Uma cadeia de caracteres é formada por um agregado de caracteres. Uma matriz é um conjunto homogêneo de dados cujo elemento individual é identificado por sua posição no agregado em relação ao primeiro. Um vetor é uma matriz com tamanho 1 x n, em que n é o número de elementos do vetor. O tipo do registro é formado por diversos campos. Veja um vetor (ou uma matriz 1 x 4): Algoritmo
Bernard
Claudio
Celso
O vetor apresentado pode ser declarado assim: engenheiros:vetor [4] cadeia de caracteres. Nome_Vetor:vetor[tamanho]tipo. Os operadores indicam a realização de alguma ação ou verificação “entre” elementos. Ao pesquisar operadores, podemos encontrar algumas variações na classificação. Os operadores mais citados são os Matemáticos(ou aritméticos), Lógicos e Relacionais. Além desses três, Laços utilizarão expressões ou relações condicionais – e que conterão operadoradores – como forma de finalizar uma ação repetitiva. Os operadores e a estrutura de Laços são descritos a seguir. 1. Matemáticos
OPERAÇÃO
OPERADOR
adição
+
Subtração
-
multiplicação
*
Divisão
/
Módulo
MOD
Quociente
DIV
Quadro 3 - Operadores matemáticos. Fonte: Wikilivros Contributors, 2015.
23
Lógica de programação
2. Operadores Lógicos
OPERAÇÃO
OPERADOR
(and)
E
ou (or)
OU
não (not)
~ ou !
Quadro 4 - Operadores lógicos. Fonte: Adaptado de Wikilivros Contributors, 2015.
3. Relacionais
OPERAÇÃO maior
OPERADOR >
maior ou igual
>=
menor
<
menor ou igual
<=
igual
=
diferente
~= ou <>
Quadro 5 - Operadores relacionais. Fonte: Wikilivros Contributors, 2015.
4. Condicionais (ou blocos de seleção) Para estruturar condições, utiliza-se o formato seguinte.
SE (...) ENTÃO (...) SENÃO SE (...) ENTÃO (...) SENÃO (...) Tabela 1 - Estruturas condicionais. Fonte: Wikilivros Contributors, 2015.
24 Laureate- International Universities
Outra forma utilizada seria:
SELECIONE (...) DENTRE [valores]: (...) SAIA Tabela 2 - Estrutura para selecionar em uma lista. Fonte: Wikilivros Contributors, 2015.
Os operadores condicionais são incluídos em expressões como: variável = (expr1) ? (expr2) : (expr3) Essa expressão equivale a: Se(expr1) ENTÃO expr2; SENÃO expr3; 5. Laços – estruturas dos laços de repetição (loops) utilizam condições e operadores para controlar a finalização de ações repetidas:
ENQUANTO (...) FAÇA (...) Outra forma: PARA var <- 1,2,...,20 FAÇA (...) Outra forma: FAÇA (...) ATÉ (...) Tabela 3 - Estrutura de um loop (laço). Fonte: Wikilivros Contributors, 2015
Veja o exemplo a seguir e tente descobrir o que ele faz. O algoritmo pode ser executado, por exemplo, logo após o usuário clicar em um botão, depois de preencher dois campos com números (do tipo inteiro).
25
Lógica de programação
num1,num2,result: inteiro inicio leia (num1) leian(num2) result < num1+num2 escreva (result) fim Tabela 4 - Algoritmo para somar. Fonte: Elaborada pelo autor, 2015.
Se quiser verificar o que acontece em um programa real, acesse <http://www-k12.atmos.washington.edu/~ovens/javascript/jseg26.html>, preencha os campos com 2 e 5 e clique no botão <answer> :
Figura 6 - Calculadora. Fonte: Universidade de Washington, 2015.
Assim, para somar duas parcelas, por exemplo 2 + 5, o computador armazenará cada um dos dois valores (2 e 5) em áreas de memória (segundo o algoritmo de exemplo, num1 e num2) e, em seguida, vai somar esses valores e depositar o resultado em outra área (com nome da variável result). Um programa que soma dois valores pode esperar um valor em um área e outro valor em outra área e, depois de você digitar os valores, o programa pode somá-los. Então, se você digitar 2 em um campo e 5 em outro, após realizar a soma, o programa armazenará o valor 7 em um terceiro local. Porém, se você teclar 3 ao invés de 2, o resultado será 8. O que aconteceu? O valor armazenado na área destinada para a primeira parcela mudou, variou.
26 Laureate- International Universities
Figura 7 - Calculadora com um novo valor para uma das parcelas. Fonte: Universidade de Washington, 2015.
O que acontece quando clicamos no botão “answer” (resposta): 1. o valor da primeira caixa de texto (3) é armazenado em uma área de memória (uma variável); 2. o operador selecionado na lista de operadores (“+”) é armazenado em outra variável; 3. o valor da segunda caixa de texto (5) foi armazenado em uma terceira variável; 4. o sistema realiza a operação escolhida e armazena o resultado em uma nova variável, utilizando cada um dos valores armazenados nas duas variáveis. Se o operador for “+”, o sistema soma as parcelas; se for “*”, o sistema vai multiplicar as parcelas, e assim acontece para cada um dos operadores; 5. o sistema apresenta o resultado da operação na caixa de texto que aparece na tela (8). As linguagens de programação tratam tanto valores que não mudam quanto valores que se alteram ao longo do tempo e de acordo com determinadas ações programadas. No exemplo anterior, quando você variou o valor de 2 para 3, a primeira parcela mudou, variou. Você até poderia ter variado a segunda parcela, mas não fez. Você a manteve com o valor 5. Se, por exemplo, você souber que sempre a segunda parcela será 5, não há razão para deixar alguém digitar algum valor. A tela pode, então obter um valor que sempre será somado ao 5. Ou seja, o 5 é um valor mantido. O valor que varia será sempre somado ao de uma constante. É importante conhecer a Recursão, pois ela trata de casos nos quais uma função pode chamar a si mesma. Veja um exemplo clássico, com o fatorial. ALGORITMO: Fatorial(n) ENTRADA: inteiro n SAÍDA: fatorial de n REQUISITOS: n >= 0 SE n <= 1 RETORNE 1 SENÃO RETORNE n * Fatorial(n-1)
27
Lógica de programação
Note que existe uma chamada para a Fatorial(x) que vem de dentro do próprio código (veja a última linha). Vamos compreender as variáveis utilizando exemplos do dia a dia. Pense, por exemplo, em uma planilha, usada para controlar custos em obras, fábricas, escritórios etc. Imagine que uma empresa de recursos humanos (RH) seleciona e contrata recursos para uma empresa de engenharia ou para determinada indústria. Por cada contratação, ela recebe 10% de comissão. O diretor pediu para um funcionário elaborar uma planilha com os valores referentes ao somatório de salários dos funcionários indicados. Esses valores deveriam estar separados segundo cada uma das categorias. Veja a planilha elaborada.
Recursos
Valor R$
comissão %
Engenheiros
100.000
10.000
Administradores Locais
125.000
12.500
Pessoal Operacional
68.500
6.850
Suporte e Serviços
225.000
22.500
Máquinas e Equipamentos
78.100
7.810
Custo externo ou indireto
57.100
5.710
Custo total de recursos
653.700
65.370
10
Quadro 6 - Planilha com custos de recursos. Fonte: Elaborada pelo autor, 2015.
Análise das colunas 1 e 2: note que a primeira e segunda coluna formam uma área mais escura, que está preparada para que o usuário preencha as células da planilha com valores, que podem ser nomes ou números. Na primeira, são nomes de categorias; nas colunas 2 e 3, com valor e comissão, esses valores serão numéricos. Análise da coluna 3: a terceira coluna indica um valor que é calculado. Ele depende de quais colunas? Apenas da segunda, que contém o valor. Em cada linha, o valor será o resultado da multiplicação do número da segunda coluna por 10%, ou seja, multiplicando por 10 e dividindo por 100. Na planilha, você pode programar o cálculo dos valores da coluna 3 que utilizem valores da segunda coluna e multiplicá-los por 0,1 (ou 10/100, ou seja, aplicar 10%). Nesse caso, você estará considerando o percentual de 10% como constante, ele não deve variar. Porém, se um dia, em uma nova negociação, esse valor for modificado para 15%, você deverá alterá-lo em cada uma das células em que estiver multiplicando os valores da segunda coluna por 10%. Inclusão da coluna 4: para evitar esse transtorno, você pode incluir uma área de memória que vai armazenar o valor que será multiplicado. É exatamente isso que ocorre quando, na quarta coluna, for inserido o valor 10. A fórmula de multiplicação em cada uma das células da coluna 3 passará a considerar não mais o valor 10, mas o valor que estiver na primeira linha (dos cabeçalhos de coluna) e na quarta coluna.
1.3.1 Variáveis e outros elementos que compõem linguagens de programação As variáveis são muito importantes para os programas. Toda linguagem de programação apresenta comandos para a definição (ou declaração) das variáveis. De acordo com Tucker (2008), existem três princípios a serem considerados em linguagem de programação: 28 Laureate- International Universities
• sintaxe: a linguagem de programação é composta de comandos. Para que o compilador
entenda, há a necessidade de que as palavras que formaram os comandos, assim como as “frases” utilizadas obedeçam uma estrutura, estejam organizadas, sigam uma regra. Por exemplo, ao interpretar “a = b + c;” o compilador reconhece os operadores “=” e “+” e identifica o final do comando pelo “;”. A sintaxe indica que o que vem antes do sinal “=” é uma variável que armazenará o resultado da expressão que está logo em seguida ao sinal “=”. Além disso, para algumas linguagens, a sintaxe exigirá que antes e depois dos operadores exista um espaço em branco. O compilador sabe que deve somar as variáveis ou constantes que estiverem antes e depois do sinal “+”. Assim, a sintaxe permite que o compilador some os valores contidos nas variáveis “b” e “c” e armazene o valor resultante da soma na variável “a”.;
• nomes e tipos: associados ao vocabulário das linguagens de programação, com regras para dar nomes a entidades (variáveis, procedimentos, parâmetros) e o escopo de visibilidade (algumas variáveis podem perder o valor após serem declaradas e utilizadas em um local específico, outras funcionarão e manterão o valor armazenado ao longo de todo o tempo). Os tipos definem como os valores devem ser manipulados. Tipos bem elaborados podem resultar em algoritmos mais eficientes e legíveis;
• Semântica: trata do significado de cada comando e os efeitos que causam nas variáveis.
Por exemplo, o comando “a = b + c;” significa: “Some os valores armazenados nas variáveis “b” e “c” e armazene o resultado na variável “a”.
1.3.2 Tipos de variáveis O exemplo apresentado com a soma de parcelas trabalha com três variáveis numéricas. Diferentemente da tela de soma, a planilha apresentada com o exemplo de Custos e Comissão utiliza variáveis alfanuméricas e numéricas. Outra classificação comum é relacionada com o contexto do programa. As variáveis são classificadas em variáveis locais e globais. Um bom exemplo facilitará o entendimento desse conceito. Imagine que equipes de engenheiros em duas fábricas decidem participar em um torneio de vôlei. Os engenheiros da fábrica A já estão na mesma equipe há bastante tempo e se chamam por apelidos. O grande destaque é o engenheiro Tom. Seu nome não é Antônio, como você poderia supor. Ele é chamado dessa forma por ter três gatos, e seus amigos o apelidaram por causa da conhecida dupla “Tom e Jerry”, dos desenhos animados. O time da fábrica A vai jogar pela primeira vez contra um time desconhecido, da cidade vizinha. Os jogadores de um time não conhecem os nomes dos jogadores do outro. Assim, os oponentes não sabem quem é o Tom, muito menos que ele é uma “ameaça” com suas incríveis cortadas. Tom é conhecido somente pelo pessoal de sua cidade. Agora, imagine que o jogo é entre equipes formadas por alunos de uma mesma turma de um colégio. Apesar de serem equipes diferentes, todos conhecem os nomes dos jogadores de outro time. Tom é o apelido do Jair, e todos da cidade o conhecem como Tom. Seu apelido é local. Em um contexto bem semelhante, temos um torneio entre cidades mais próximas de uma região, no qual os participantes realizam churrascos mensais e todos se conhecem pelo nome ou apelido. A relação de conhecimento entre todos é global. Nos programas de computador acontece algo semelhante. Algumas variáveis são criadas e reconhecidas apenas em um trecho do programa. Ao terminar a execução de determinada tarefa ou 29
Lógica de programação
sequência de ações, o resultado é enviado para algum local, e a variável local, que já cumpriu a sua função, não será mais útil e nem reconhecida em outros trechos do programa. Para finalizar seus estudos sobre os conceitos básicos de lógica de programação, acompanhe um exemplo de algoritmos com definições de variáveis. O procedimento Encontre_o_max() foi adaptado do exemplo oferecido por Kuchling (2012). Vamos entender o problema, apresentar uma proposta de algoritmo e ver como foi implementado em uma linguagem, nesse caso, em Python
• Problema: dada uma lista de números positivos, retorne o maior número da lista. • Entrada: uma lista L com números positivos. A lista precisa ter pelo menos um número. • Saída: um número n, que é o maior número da lista. Algoritmo para Encontre_o_max(): 1. atribua a max o valor 0. 2. para cada número x da lista L, compare com max. Se x for maior, atribua x a max. 3. max passa a conter o maior valor da lista. A implementação na linguagem Python ficaria assim: def find_max (L): max = 0 for x in L: if x > max: max = x return max Um algoritmo não pode ser ambíguo, deve ter definidas entradas e saídas, precisa ter seu término garantido (para não ficar eternamente executando) e deve produzir o resultado correto. O exemplo obedece a todos os quesitos.
30 Laureate- International Universities
Síntese Síntese
• Lógica
pode ser entendida como coerência de raciocínio, de ideias, ou o modo de raciocinar peculiar a alguém ou a um grupo.
• A lógica e a modelagem nos ajudam a resolver problemas, utilizando o computador, uma máquina que processa dados e os transforma.
• Os algoritmos oferecem um passo a passo para se cumprir determinada tarefa e envolvem três elementos: problema, entrada e saída.
• As variáveis armazenam valores para serem processados. • Variáveis devem ser sempre declaradas e contêm atributos como nome, tamanho e tipo, e podem ser locais ou globais.
• Variáveis
locais: assumem um valor reconhecido somente em determinado trecho do programa. Uma vez terminada a tarefa naquele trecho, as variáveis não são mais reconhecidas.
• Variáveis globais: mantêm suas características e o valor ao longo de toda a execução, em todos os trechos do programa.
Referências Bibliográficas
AHO, A. V.; SETHI, R.; ULLMAN, J. D. Compiladores: princípios, técnicas e ferramentas. 2. ed. São Paulo: Pearson, 2008. BINDER, F.; DIRENE, A. I. Conceitos e ferramentas para apoiar o ensino de lógica de programação imperativa. In: Anais do X Simpósio Brasileiro de Informática na Educação. Curitiba. 1999. CHAMOVITZ, I. Apostila: iniciação à lógica clássica. UFRJ, mar. 2003. Disponível em: <http:// www.api.adm.br/ufrj/logica/tutorial.htm>. Acesso em: 23 mar. 2015. FERREIRA, A. B. de H. Novo dicionário da língua portuguesa. 2. ed. São Paulo: Nova Fronteira, 1986. FONTES, C. Breve história da lógica. Disponível em: <http://afilosofia.no.sapo.pt/Hist. htm>. Acesso em: 23 mar. 2015. FORBELLONE, A. L. V.; EBERSPÄCHER, H. F. Lógica de programação. São Paulo: Pearson Prentice Hall, 2005. IBM. Afinal, o que é ALM (Application Lifecycle Management)? Disponível em: <https://www.ibm.com/developerworks/community/blogs/rationalbrasil/entry/alm?lang=en>. Acesso em: 26 jul. 2014. LIMA JÚNIOR, F. C. Lógica e matemática discreta. 8-10 mar. 2010. Notas de aula. KUCHLING, A. M. 50 examples for teaching Python. 2012. Disponível em: <https://fiftyexamples.readthedocs.org/en/latest/intro.html>. Acesso em: 23 mar. 2015. MEDINA, M.; FERTIG, C. Algoritmos e programação. São Paulo: Novatec Editora, 2005. MICHAELLIS. Michaelis Moderno Dicionário da Língua Portuguesa. Disponível em: <http://michaelis.uol.com.br/moderno/portugues/>. Acesso em: 23 mar. 2015. OKA, C.; ROPERTO, A. Alan Turing (1912-1954) pioneiro na lógica de computadores. Disponível em: <http://www.cotianet.com.br/BIT/hist/turing.htm>. Acesso em: 23 mar. 2015. ORENSTEIN, J. Receita de massa de pastel de feira. Disponível em: <http://blogs.estadao.com.br/paladar/pastel/>. Acesso em: 23 mar. 2015. PORTAL DE TRINDADE. Como chegar em Trindade. Disponível em: <http://www.paraty. com.br/trindade/comochegar.asp>. Acesso em: 23 mar. 2015. SEBESTA, R. W. Conceitos de linguagens de programação. Tradução de José Carlos Barbosa dos Santos. 4. ed. Porto Alegre, RS: Bookman, 2000. TUCKER, A. B; NOONAN, R. E. Linguagens de programação: princípios e paradigmas. 2. ed. São Paulo: McGraw-Hill, 2008.
32 Laureate- International Universities
UNIVERSIDADE DE WASHINGTON. Calculator. Disponível em: <http://www-k12.atmos.washington.edu/~ovens/javascript/jseg26.html>. Acesso em: 24 mar. 2015. XAVIER, D.W. Fluxograma e pseudocódigo. TI Expert: on-line. Disponível em <http://www. tiexpert.net/programacao/algoritmo/fluxogramas-e-pseudocodigo.php>. Acesso em: 26 mai. 2015. WIKILIVROS CONTRIBUTORS. Algoritmos e Estruturas de Dados/Sintaxe. Disponível em: <http://pt.wikibooks.org/w/index.php?title=Algoritmos_e_Estruturas_de_Dados/ Sintaxe&oldid=213132.> Acesso em: 23 mar. 2015.
33
Capítulo 2 Dados: Entrada e Saída
Introdução Você já deve ter percebido que agir ou pensar em lógica implica um fluxo pelo qual a informação será processada, ou seja, deve-se considerar, basicamente, um problema a ser resolvido, a entrada para esse problema, e a saída, que será a solução. Mas como trabalhar com esses aspectos? Um engenheiro precisa atuar de forma sistêmica, considerando todo o ambiente, podendo dividi-lo em partes e realizando a análise dessas partes e das suas relações. O pensamento sistêmico permite analisar e compreender o problema como um sistema integrado e resolvê-lo a partir de dados coletados, processamento e saída. Um programa lê dados, processa-os e os envia para algum local de armazenamento, ou ainda divulga-os em diversos possíveis dispositivos de saída: impressoras, monitores e caixas de som, por exemplo. Então, o que acontece se os dados de entrada forem ruins, incompletos, errados ou desatualizados, mesmo que se obtenha o melhor sistema de informação? E se todos os cálculos estiverem corretos mas o relatório final estiver em um formato inadequado, ilegível ou incompreensível? Isso não pode acontecer. Portanto, podemos concluir que a qualidade dos dados que entram no sistema é fundamental. E se não for, o sistema deverá tratá-los, excluindo ou acertando, sempre que possível, os dados que estiverem com problema ou errados. Este capítulo apresenta elementos fundamentais sobre a entrada de dados e a saída de dados, ou informação. Você entenderá os diferentes tipos de dados e saberá como tratá-los e como é possível apresentá-los.
2.1 Tipos de dados Quando um programador recebe um sistema para desenvolver, ele sabe que precisará basicamente de três informações. 1. Saber o objetivo final do sistema, ou seja, qual é a saída – imagine um sistema que lista projetos com mais de uma semana de atraso. Nesse caso, o programador sabe que a saída será uma série de registros com datas e algumas outras informações. 2. Saber a fonte dos dados e como são os dados de entrada do sistema – de onde vêm os dados e que tipo de dados serão processados. No caso da lista de projetos em atraso, o programador precisa saber se ele vai coletar os dados em cada local, filial, obra, fábrica, ou se os dados já estão concentrados em um local específico, por exemplo, na matriz. Outra questão é: os dados estão em que formato? 3. Como ele vai processar esses dados para transformar o que entra e obter o resultado desejado na saída.
35
Lógica de programação
Ao utilizar uma linguagem, você estará lidando com três tipos básicos (ou primitivos) de dado: 1. numérico: pode ser real ou inteiro; 2. literal: pode ser um caractere ou uma cadeia de caracteres; 3. lógico: assume um dos valores: verdadeiro ou falso. Além dessas três possibilidades, algumas linguagens permitem trabalhar alguns outros tipos derivados ou estendidos, como data e hora, por exemplo, ou ainda tipos formados por estruturas, como um registro composto de vários campos, cada um assumindo um tipo básico. Lembre-se de que existem variações de linguagem para linguagem. Então, a melhor forma de identificar e utilizar os diversos tipos de variáveis associados a determinada linguagem de programação é buscando o manual. Geralmente, existem diversos tipos: o manual de referência oferece mais informação em um formato preparado para consulta, e o manual de usuário apresenta as informações em uma forma mais voltada ao aprendizado.
VOCÊ O CONHECE? Edsger Wybe Dijkstra (1930-2002), nascido em Roterdã, na Holanda, foi um cientista da computação reconhecido por estudos nas áreas de desenvolvimento de algoritmos, programas, e linguagens de programação. Entre suas contribuições, podemos citar o algoritmo para o problema do caminho mínimo (algoritmo de Dijkstra) e a construção de semáforos para coordenar múltiplos processadores e programas. O estudioso recebeu o Prêmio Turing em 1972.
2.1.1 A importância da definição do tipo de dado Qual a importância em se definir o valor a ser calculado para um campo de dado que representa uma medida? Pense em alguém digitando a idade atual de um visitante em uma tela de cadastro e precisando completar as casas decimais com zeros. Por exemplo, uma pessoa com 23 anos teria seus dados digitados como 23,0000. Isso exigiria que o digitador teclasse 6 vezes, ou seja, duas vezes para incluir a idade 23 e mais quatro para completar com os zeros. Seria um grande desperdício de esforço, tempo e dinheiro (supondo que o digitador é pago por hora). Esse problema mostra que a operação de entrada de dados pode sofrer perdas com a má definição de variáveis. Messias Trajano é o engenheiro responsável pelas obras de uma empresa de logística que atua no eixo Rio–São Paulo. Ele contratou recentemente um estagiário, Adalberto Matias, para ajudá-lo em um projeto bem importante: a construção de um website para ajudar no mapeamento de algumas construções com inclusão de detalhes de acesso. O estagiário ficou responsável pela definição de campos de dados e precisa pensar, neste momento, em um campo para ser definido: distância. Adalberto Matias precisa oferecer de maneira bem prática, no website que está construindo, uma distância aproximada entre os escritórios e alguns locais de referência: a praça, o restaurante conhecido, o cinema. Também será necessário comparar distâncias aproximadas entre os locais de distribuidores e fornecedores.
36 Laureate- International Universities
A partir dessa demanda, Adalberto Matias define um campo “distância” como um valor inteiro, com dez algarismos, que será medido em metros. Como os locais funcionam apenas no Rio de Janeiro e em São Paulo, esse limite é o suficiente. Entre os dois Estados, esse campo poderia assumir um valor em torno de 455.000 metros. Entre duas filiais, em São Paulo, no mesmo bairro, poderia ser de 400 metros, por exemplo. O valor inteiro foi escolhido e atenderá bem aos requisitos.
400m
455km
Figura 1 – Distância aproximada entre prédios. Fonte: Elaborada pelo autor, 2015.
Porém, Adalberto Matias foi orientado para atuar em um sistema de construção de casas populares. O mesmo campo “distância” medirá o espaço entre as residências, que ficarão bem próximas uma das outras, bem como a distância das calçadas e dos bueiros em relação aos imóveis e aos postes de luz. Adalberto pensou: será que um valor inteiro servirá para esse propósito?
4,5m
4,5m
4,5m
Figura 2 – Casas bem próximas com uma marcação de distância em 4,5 metros. Fonte: Elaborada pelo autor, 2015.
Uma casa pode estar afastada 4,5 metros de outra. Se o sistema for definido com campo inteiro, ele não terá decimais e não poderá registrar o meio metro a mais, o que poderá causar problemas. Em situações ainda mais críticas, certos cálculos não podem perder informação. Em uma fábrica, por exemplo, alguns campos precisarão de mais de uma casa decimal, possivelmente com precisão de até 5 ou mais casas, para que o cálculo seja realizado e resulte em um valor confiável. Isso porque, quando mal definidos, os valores resultantes de cálculos podem causar acidentes e catástrofes. Por essa razão, quando Adalberto Matias for definir o banco de dados, será necessário que ele entenda os três momentos: entrada, processamento e saída:
37
Lógica de programação
• entrada: facilitar a entrada de dados e oferecer menos possibilidade de erros; • processamento:
entender que cálculos serão realizados e o impacto que a redução de casas decimais pode causar no resultado final, por exemplo, ao multiplicar e dividir números decimais;
• saída: garantir que o resultado será de acordo com o esperado, confiável, sem perda de informação.
Uma segunda questão a ser considerada pelo estagiário diz respeito à otimização do sistema. A memória do computador é formada por espaços e é medida em bytes. Adalberto pode definir como cadeia de caracteres com tamanho 10 um campo que assumirá valores “VERDADEIRO” (que ocupará 10 bytes na memória) ou “FALSO” (que ocupará os mesmos 10 bytes e deverá preencher os cinco caracteres finais da palavra com espaços). A definição de um campo como lógico ocuparia menos espaços e permitiria o tratamento mais adequado para o sistema. O caso apresentado, no qual o desenvolvedor precisa definir dados, é bastante comum. Afinal, processos mudam: a empresa é uma organização viva, em constante transformação. Podemos tentar evitar os problemas, prevendo-os, utilizando boas práticas. Outra dúvida comum aparece na definição de um campo de data. Grande parte das linguagens permite criar um campo do tipo data e hora, ou somente data – que, na verdade, é uma extensão do tipo real, mas que o sistema converte para o formato de dia, mês e ano ou, ainda, horas, minutos e segundos. Ao definir que uma data será armazenada em uma sequência de caracteres, estaremos criando a necessidade de transformar essa sequência em um formato que permita a realização de cálculos, para, por exemplo, saber quantos dias foram trabalhados. Por exemplo, imagine o campo data_de_inauguração, char (8), que recebe um valor para registrar a inauguração de uma filial: data_de_inauguração:= “25032015” Para saber há quanto tempo a loja está funcionando, em dias, haverá a necessidade de conversão. Para isso, será preciso converter em dias o dado desse campo, o que implica capturar três partes da sequência (os dois primeiros dígitos para o dia, os dígitos 3 e 4 para o mês e os dígitos 5, 6, 7 e 8 para o ano). Note que, se o arquiteto de dados optasse por definir o campo na sequência “ano, mês e dia” ao invés de “dia, mês e ano”, ele poderia ordenar o campo mais facilmente. Observe: se houver três registros como os seguintes, eles não ficarão ordenados:
• “12042015”; • “13052015”; • “25032015”. O sistema, ao ordenar caracteres, coloca o registro que tem o número 1 como primeiro caractere na frente do registro que inicia com 2. Assim, a data correspondente ao mês de março acaba aparecendo após os meses de abril e maio.
38 Laureate- International Universities
Agora, veja como seria ordenado, caso a sequência fosse “ano, mês e dia”:
• “20150325”; • “20150412”; • “20150513”. Agora, as datas estão em ordem cronológica: o mês de março primeiro, seguido de abril e maio. Assim, perceba que existe certa lógica ao definir uma sequência para representar datas, iniciando por ano e apresentando mês e dia em seguida. Um dos grandes problemas em se definir a data como uma sequência de caracteres é a dificuldade de controle. Por exemplo, haverá a necessidade de controlar se um ano é bissexto. Nesses casos, se o campo já está definido como sequência de caracteres, opta-se por gerar uma variável durante o processamento, que será do tipo “data” (em inglês, date) e que aproveitará recursos da linguagem para oferecer um mais controle e facilidades para a operação. Se o valor armazenado no campo com sequência de caracteres precisar ser atualizado, após os cálculos utilizando a variável de tipo data, será necessário converter novamente a estrutura, recuperando dois dígitos para o dia, dois para o mês e quatro para ano, concatenando os caracteres na sequência esperada pelo campo de data. Outra opção para armazenar datas é utilizar um tipo “date”. Muitas linguagens oferecem tipos de variáveis para representar datas, com a grande vantagem de disponibilizarem também formas para realizar cálculos utilizando-as. São funções pelas quais você pode passar parâmetros e obter resultados. Por exemplo, algumas linguagens reconhecem que uma operação de subtração entre datas deve realizar a conversão de cada uma das datas para dias e subtrair os dias, dando o resultado em dias. Ou, ainda, subtraindo um inteiro de uma data, o resultado será a data com x dias a menos.
NÃO DEIXE DE VER... Assista ao filme A Rede Social (Sony Pictures Brasil), dirigido por David Fincher e lançado em 2010, para perceber como o conhecimento em programação e o desenvolvimento de um sistema resultaram em sucesso.
2.2 Entrada e saída de dados Você viu que a programação tem três partes: entrada, processamento e saída. Usuários em geral conhecem apenas duas: entrada e saída. Eles não querem saber como a entrada é processada. Querem que o resultado esteja correto, seguindo determinadas regras. Veja um exemplo bem simples, com uma calculadora. Você pode experimentar entrando no site <http://web20calc.com>.
39
Lógica de programação
Figura 3 – Calculadora. Fonte: <http://web2.0calc.com>.
Ou, então, consiga uma calculadora simples ou imagine que está operando uma. Seu objetivo é efetuar uma soma. Vamos usar como exemplo 5 + 2. A sua entrada de dados é: <C> , <5>, <+>, <2>
Para que o sistema entenda que esses dados devem ser utilizados para calcular a operação – nesse caso, a soma –, você precisa finalizar e comandar o início do processo de cálculo. A tecla igual “=” foi programada para realizar a operação armazenada a partir do que você digitou antes de teclá-la. Ou seja, ao pressionar “=”, o sistema inicia um processo que você, como usuário, nem sequer se dá conta, pois o que deseja de verdade é olhar o resultado, que será apresentado em milésimos de segundos. Nesse tempo curto, a máquina alocou espaço de memória em variáveis e executou operações de atribuição (atribuiu valores 5 e 2 para variáveis) e executou a soma do conteúdo dessas variáveis, armazenando o resultado em algum espaço da memória e, finalmente, apresentando-o no visor de sua calculadora. Tudo muito rápido. Você não quer saber da memória e do cálculo – digitou a sequência de entrada e checou o resultado. Em outras palavras, o usuário tem entrada e saída.
2.2.1 A Importância da Entrada e Saída de Dados A entrada de dados é fundamental para se obter bons resultados. Assim, deve-se trabalhar bem a entrada, criticando os dados a fim de evitar possíveis problemas no processamento e, pior, resultados errados. Imagine um sistema de recursos humanos indicando que um paciente de sexo masculino está entrando em trabalho de parto, uma vez que a tela de entrada de dados não bloqueia esses campos quando o paciente não for do sexo feminino. Consegue compreender a importância no tratamento da entrada de dados? Existem duas formas básicas para os dados entrarem em um sistema: 1. diretamente: por força e vontade do usuário; 2. indiretamente: por captura, geralmente automática ou programada. 40 Laureate- International Universities
A entrada de dados direta, feita pelo usuário, inclui a digitação de informação em telas preparadas para captura de dados. No momento em que você informa que deseja fazer o download de um livro gratuito e entra com seu nome e e-mail na tela que aparece em seu vídeo, você está entrando com dados em um sistema. E o que acontecerá com esses dados depende do sistema, dos objetivos do responsável pelo site. Por exemplo, pode ser que mais adiante você receba por e-mail a oferta de algum produto ou serviço. A entrada indireta ocorre por captura. Hoje, existem dados espalhados em diversos locais. Empresas passam por fusões e aquisições e acabam tendo de integrar sistemas. Dados são recuperados e fluem de um sistema a outro. Para que a integração funcione, é preciso que os dados estejam definidos de forma similar. Da mesma forma que a entrada de dados direta, a indireta deve passar por críticas antes de ser integrada ao sistema.
NÃO DEIXE DE LER... Você pode observar um exemplo de captura indireta no site do Centro de Estudos sobre as Tecnologias da Informação e da Comunicação (CETIC.br), disponível em <http:// www.cetic.br>. Nele, é possível acessar e utilizar dados de pesquisas sobre o acesso e uso da internet.
Um exemplo interessante acontece por meio de redes sociais. Um programa de entrevistas levado ao ar “ao vivo” pode pedir a opinião de telespectadores utilizando o Twitter e capturar suas percepções e expectativas. Assim, a direção toma decisões ainda durante a transmissão. Outro exemplo de dados capturados automaticamente ocorre pelo mapeamento de carros utilizando GPS ou triangulação de antenas, sistema que calcula a posição do carro utilizando cálculos estimados a partir da localização conhecida de antenas.
2.2.2 Trabalhe mais a entrada de dados e evite problemas na saída Vamos retomar o exemplo da nossa calculadora que efetuou a soma 5 + 2. Algumas considerações sobre entrada de dados nesse exemplo simples se repetem em sistemas complexos. 1. Ao usar a calculadora para somar 5 + 2, se o usuário errar e digitar 6 ao invés de 5, o resultado será diferente. 2. Se o usuário não perceber que o resultado foi diferente do esperado, encontrará problemas. 3. Assim, deve-se buscar alguma forma de checar a consistência do resultado. Por exemplo, digitar novamente, fazer a conta inversa (nesse caso, o resultado (6 + 2) menos a segunda parcela (2) não será igual à suposta primeira parcela (5). 4. Algumas checagens já são previstas para números. O uso de dígitos verificadores ao final de um número é um exemplo. Os dígitos são calculados utilizando os números que compõem o campo. Por exemplo, em uma sequência de números, poderíamos somá-los e obter um dígito verificador. Assim, teríamos 11-2, 12-3, 13-4, 25-7. Porém, para garantir mais consistência, um cálculo mais complexo é realizado para campos importantes como CPF, CNPJ e outros códigos. Alguns cálculos podem ser obtidos na internet. Erros devem ser evitados logo na tela de entrada de dados. Cada campo pode ter uma crítica. Por exemplo, o campo CPF pode checar o dígito verificador e não permitir que o registro seja incluído enquanto o CPF não esteja com o dígito correto. Ou, ainda, o e-mail deve conter um caractere “@”. Muitos campos são obrigatórios, e o digitador não poderá seguir adiante en41
Lógica de programação
quanto não preenchê-los com valores válidos, checados pelo sistema, segundo a lógica e as regras preestabelecidas. Apesar de todas as diretrizes indicarem que erros devem ser evitados logo na entrada de dados, existem situações em que o momento exige a captura dos dados em alta velocidade. Durante uma aula, se algum estudante está tomando nota e digitou errado ou sem acentuação, ou ainda faltando algumas letras em palavras, ele estará muito mais preocupado em recuperar o que está sendo falado naquele minuto do que se a palavra que escreveu no instante anterior está errada. Afinal, depois da aula, ele pode corrigir todo o texto. Esse é um exemplo simples, mas pode ser aplicado em sistemas mais complexos. A crítica pode ser feita a cada entrada de dados ou executada em lote, após os dados entrarem no sistema. O que vai determinar como será feito será o conjunto de características do sistema, os requisitos do usuário e a urgência em se obter os dados. Se a crítica em uma tela de entrada de dados leva 30 segundos para consultar cadastros antes de aceitar o registro e temos apenas dois campos a serem preenchidos, com taxa de erro de menos de 1%, talvez seja melhor deixar o sistema criticar no final do dia todos os registros castrados ao longo do período. O que não pode acontecer é o sistema acatar registros com erro, que resultarão em valores inúteis.
2.2.3 O acesso aos dados Para que um programa recupere informações de um banco de dados, é preciso seguir alguns passos. Dependendo da linguagem, a sintaxe pode variar, mas, em geral, a sequência será a seguinte. 1. Se o arquivo a ser lido estiver disponível remotamente, em um servidor na web ou em outro computador, o programa deve estabelecer uma conexão com o servidor (computador) no qual está o arquivo. 2. Em seguida, o programa vai procurar o arquivo no local indicado. Em alguns casos, o sistema consegue localizá-lo automaticamente e guarda essa localização em alguma variável que será utilizada nos passos seguintes. 3. O endereço do local onde está o arquivo já está em uma variável. Arquivos com o mesmo nome podem estar em endereços distintos e, assim, podem ser diferentes. 4. O sistema deve identificar o “motivo” do acesso ao arquivo antes de abri-lo. Por exemplo, o arquivo pode ser aberto somente para “leitura”, para “gravação” ou para “leitura e gravação”. 5. Uma vez conseguida a conexão e encontrado o arquivo, o sistema tenta abri-lo, de acordo com o “motivo”. 6. Se houver sucesso em abrir o arquivo, ele estará pronto para ser lido ou gravado, de acordo com a estrutura montada para tal. 7. Sempre depois de realizar a leitura ou gravação, o arquivo deve ser fechado e, também, liberada a conexão. Resumindo, o sistema deve:
• estabelecer conexão com o outro computador (em que está o arquivo); • identificar o local do arquivo; • tentar abri-lo de acordo com o motivo desejado; 42 Laureate- International Universities
• ler o arquivo; • mover valores dos campos do arquivo para estruturas guardadas em memória (ou seja, variáveis de memória);
• fechar o arquivo; • desconectar do outro computador. Trabalhar com o arquivo aberto não é recomendado em boa parte das aplicações, mas pode ser indicado em alguns casos especiais, quando é necessário fazer muitas alterações ou uma recuperação no banco de dados.
NÓS QUEREMOS SABER! O que são bibliotecas de programação? Ao desenvolver um sistema de computação, certos conjuntos de comandos são executados repetidamente. Então, juntam-se subprogramas em uma biblioteca. Bibliotecas são formadas por código e dados auxiliares. Por exemplo, pode-se criar uma biblioteca de entrada de dados, pela qual existem programas específicos para criar conexão, tratar dados, realizar críticas em diversos tipos de campos. Outra biblioteca pode conter elementos de interface, elementos visuais, que facilitam a interação do usuário durante a entrada de dados.
2.3 Tipos de estruturas de dados Agora, você conhecerá os tipos mais comuns de estrutura de dados. Trataremos aqui de vetores, matrizes e registros. Você também verá como manipulá-las. Para que você comece a entender o assunto, considere uma lista com o número de funcionários trabalhando em determinadas filiais de uma empresa. Nesse caso, ela é composta de números inteiros. A lista está em ordem do código da filial. Temos uma coluna com o código da filial e a segunda coluna com a quantidade de pessoas trabalhando. São 20 filiais. Observe:
Filial
Empregados
1
8
2
6
...
..
20
7
Tabela 1 – Lista de empregados para cada filial. Fonte: Elaborada pelo autor, 2015.
Uma lista como essa é uma matriz. Ou, ainda, podemos dizer que são dois vetores. A partir de agora, você conhecerá algumas estruturadas de dados incluindo:
43
Lógica de programação
• vetores, matrizes e registros; • listas, filas e pilhas; • árvores; • grafos. 2.3.1 Vetores Você sabe o que são vetores? Observe a sequência de custos mensais, em milhares de dólares, programados para os próximos seis meses em determinado projeto:
50,00
55,00
55,00
60,00
40,00
30,00
1
2
3
4
5
6
Tabela 2 – Sequência de custos mensais em milhares de dólares. Fonte: Elaborada pelo autor, 2015.
Esses custos são representados em uma tabela com apenas uma linha e em cinco colunas. A numeração sequencial abaixo dos valores não faz parte da tabela e servirá apenas como referência sequencial para os meses em questão. O mais importante é que o número 1 representa o primeiro mês após o início do projeto, e o número 6 representa o último mês do projeto. Alguns elementos que podemos perceber nessa estrutura:
• quantidade de meses: 6; • mês com maior valor: 4; • mês com menor valor: 6; • maior valor: 60,00; • menor valor: 30,00. Esses elementos fazem parte da estrutura que estamos abordando. Trata-se de um vetor, que é uma matriz unidimensional. Geralmente, um vetor contém x elementos, e cada elemento assume um tipo de valor, que pode ser um inteiro, um número real, uma sequência de caracteres etc. Cada valor estará associado ao índice do vetor. No vetor com os custos dos 6 primeiros meses de um projeto, o índice pode assumir valores de 1 a 6. Um programa pode recuperar o valor associado a um índice. Assim, se você deseja saber o valor do índice 4, poderá obtê-lo, bastando indicar qual o índice e em que variável deseja armazenar o valor obtido (no caso, o valor associado ao índice 4 é 60,00). Você pode declarar um vetor indicando o seu nome, a quantidade de elementos e o tipo de dado que o vetor vai armazenar em cada um de seus elementos. No caso, apresentamos 6 elementos com valores reais com duas decimais. Não se preocupe com a sintaxe, ela vai variar; e o mais importante agora é perceber a lógica: início > declaração de variáveis > procedimentos > fim.
44 Laureate- International Universities
Veja a declaração de um vetor em um exemplo para certa linguagem: int vetor_medidas[3]
Para trabalhar com valores e elementos dos vetores, você pode utilizar funções, geralmente oferecidas pelas linguagens de programação. Por exemplo, você pode usar uma função que busca no vetor o índice do elemento com o maior valor, no caso, 4. Ou, ainda, pode retornar o próprio valor, ou seja, 60! Outro requisito útil é saber navegar no vetor. Isso significa explorar todo o vetor, a partir do primeiro elemento, de índice 1. Note que não estamos nos fixando na sintaxe do pseudocódigo. Nosso objetivo é focar na lógica. O pseudocódigo está descrito a seguir, e tudo que é escrito após o tracejado não será interpretado pelo compilador, ou seja, será considerado como comentário. Note que ao terminar a linha o comentário pode continuar nas linhas seguintes. O ponto e vírgula delimita o que será interpretado como comando. Iníciodaprocedure;
------ início
var vet: array [1. .20] , real ; números reais
------- declara o vetor com 20 posições que conterão
i : integer;
-------- o índice será um inteiro
Para i := 1 to 20 faça
--------- para o índice variando de 1 até 20 faça
Leia (vetor[ i ] ) ; rente
--------- lê o conteúdo do vetor associado ao índice cor-
Escreva (vetor[ i ] ) ; corrente
--------- escreve o conteúdo do vetor associado ao índice
Fimpara; ---------- pula para o próximo índice ou, se acabou de processar o índice 20, passa ao próximo comando (fim da procedure). fimdaprocedure; Note que o vetor foi “varrido”, navegado, a partir da posição 1 até a posição 20. Para realizar essa operação, foi utilizado um loop, também conhecido como laço.
2.3.2 Matrizes “Uma matriz é um agregado homogêneo de dados cujo elemento individual é identificado por sua posição no agregado em relação ao primeiro” (SEBESTA, 2006, p. 225). Podemos dizer que matrizes são associações de vetores. Na verdade, o objetivo maior é criar uma variável única que seja composta de vários elementos contendo o mesmo tipo de informação. Esses elementos estão dispostos sequencialmente, e seu conteúdo pode ser acessado utilizando-se índices. As matrizes, quando unidimensionais, são chamadas vetores, e quando têm mais de uma dimensão, são chamadas matrizes. Veja um exemplo. Observe a sequência de custos mensais em milhares de reais, programados para os próximos seis meses em determinado projeto. Na primeira linha, inserida agora, temos uma taxa de serviço a ser aplicada a cada valor mensal, por meio de multiplicação. Assim, o valor de 50 mil reais da primeira posição ficará com resultado de 125 mil reais após a multiplicação.
45
Lógica de programação
1
2,50
2,55
3,00
3,25
3,15
2,56
2
50,00
55,00
55,00
60,00
40,00
30,00
1
2
3
4
5
6
Tabela 3 – Sequência de custos mensais em milhares de dólares, com taxa de serviço para cada valor mensal. Fonte: Chamovitz (2015).
A definição de uma matriz é bastante semelhante à do vetor, com a diferença que se define mais de um eixo. Assim, em determinada linguagem, a matriz poderia ser definida com os dois vetores: type matriz= array [1..2,1..6] of real; Repare, na declaração anterior, que a matriz é definida com duas linhas e seis colunas. E como seria para navegar na matriz? A matriz tem dois eixos: são duas linhas e seis colunas. Então, pode-se navegar na primeira linha (com x = 1) e, mantendo o x = 1, fazemos o programa variar até o elemento 6 da primeira linha. Ao atingir o sexto elemento, podemos iniciar a varredura da linha 2. Para isso, mudamos o x de 1 para 2 e iniciamos a leitura variando cada uma das colunas até chegarmos na sexta coluna. Veja o exemplo, lembrando que, em algumas linguagens, determinados símbolos iniciam comentários que não serão interpretados durante a execução. Nesse caso, diferente do anterior que utilizava “------“, o comentário inicia com “&&”. procedure imprimematriz (var mat: matriz ; x,y: integer); && mat é uma matriz. X e y são inteiros var i , j : integer;
&& Índices são inteiros;
begin
&& O sistema vai varrer a primeira linha, depois a segunda;
for i := 1 to y do
&& y vai ser a quantidade de linhas, por exemplo, 2;
begin da linha;
&& A cada início de linha, o programa varre as seis colunas
for j:= 1 to x do
&& x vai ser a quantidade de colunas, no caso, 6;
write (mat[ i , j ] ,’ ‘) ;
&& Cada célula – formada pela linha e pela coluna, será && impressa e haverá um espaço em branco após o valor;
end; end. Da mesma forma que acontece em vetores, algumas linguagens apresentam funções que ajudam programadores a identificarem o maior e o menor valor da matriz. Por vezes, será necessário ao programador desenvolver rotinas – na verdade, funções – que explorem a matriz e devolvam os valores desejados.
46 Laureate- International Universities
NÃO DEIXE DE LER... Leia o artigo O que são Vetores e Matrizes (arrays)?, de Gustavo Furtado, no site Dicas de Programação, disponível em: <http://www.dicasdeprogramacao.com.br/o-que-sao-vetores-e-matrizes-arrays/>. Nele, o autor mostra vetores e matrizes na prática e também apresenta um algoritmo muito interessante com uma função que calcula a média obtida por alunos de uma turma para saber quem foi aprovado e quem não foi.
2.3.3 Registros Você já compreendeu que, muitas vezes, é mais conveniente criar uma variável que contenha vários elementos do que tratá-los um a um, certo? Assim, em um dos exemplos vistos, criamos um vetor com valores de possíveis custos associados a seis meses de projeto. O vetor poderia ser chamado de “custos” e poderíamos, passando para uma função apenas um parâmetro (o nome do vetor), obter a média de custo do projeto. Claro, a função varreria o vetor utilizando um loop, somando cada parcela e adicionando 1 a cada elemento lido. Após chegar ao final da varredura, ou seja, depois de ler e somar o índice 6 ao total acumulado, a função dividiria o valor pelo total de elementos, no caso 6, e retornaria o valor da média para o processo que a chamou. “Um registro é um agregado possivelmente heterogêneo de elemento de dados” (SEBESTA, 2006, p. 238). Para definir um registro, deve-se criar a sua estrutura, com cada campo de registro sendo associado a um nome, um tipo e um valor inicial. Veja o exemplo utilizando a linguagem Pascal: var regforn : record fornecedor: string[30] ; telefone : longint ; endereço : string; classe : char; cnpj : integer; end;: Em C++, o registro é uma estrutura de dados. Assim, você pode criar uma estrutura de dados para armazenar uma data. Veja o exemplo: struct datadelançamento { int dia; int mês; int ano; }; Note que, sem considerar a sintaxe (pela qual um comando deve, por exemplo, terminar sempre com ponto e vírgula e uma sequência de comandos deve estar entre chaves), a estrutura segue um padrão: o nome da estrutura é seguido dos campos que a formam, e para cada campo é 47
Lógica de programação
importante indicar o tipo de variável. No caso anterior, os campos inteiros não foram limitados em duas ou quatro posições para dia, mês ou ano, mas isso poderia ter ocorrido. Veja a tabela a seguir, com comissões por indicações feitas em um período.
Recursos
Valor R$
comissão
Engenheiros
100.000
10.000
Administradores Locais
125.000
12.500
68.500
6.850
225.000
22.500
Máquinas e Equipamentos
78.100
7.810
Custo externo ou indireto
57.100
5.710
0
0
0
0
0
0
0
0
653.700
65.370
Pessoal Operacional Suporte e Serviços
Custo total de recursos
Tabela 4 – Indicações de trabalho e comissões. Fonte: Elaborada pelo autor, 2015.
Seguindo o padrão do último exemplo, poderíamos definir uma estrutura que armazenaria em memória toda a planilha. Assim: struct comissões{ char origem[30]; int valor; int comissão; }; Essas são as estruturas de dados mais comuns.
2.4 Listas, Filas e Pilhas Listas, filas e pilhas são estruturas muito utilizadas, mas nem sempre percebemos. Por exemplo, podemos fazer parte de uma lista de convidados e, na porta do estabelecimento, o pessoal da recepção vai checar se o nosso nome está nela. Ao entrar em um parque de diversões, você pode ter de entrar em uma fila para pagar pelo ticket de ingresso. Vai, então, aguardar até chegar a sua vez. E, ao entrar em um elevador com apenas uma porta, geralmente as pessoas entram e se posicionam em uma estrutura bem próxima à de uma pilha. Ou seja, a pessoa que deixou os outros entrarem primeiro vai sair primeiro. Isso também ocorre ao empilharem-se caixas com material, em um depósito. 48 Laureate- International Universities
Em cada uma destas estruturas, existem operações que podem ser realizadas. As mais comuns em estrutura de dados são:
• inclusão: inserção de um elemento; • exclusão: exclusão de um elemento; • alteração: alteração de um elemento; • ordenação: estruturação da lista de acordo com uma ordem, segundo um ou mais critérios; • localização: dada uma informação, fazer a comparação e a listagem de elementos que contenham o dado procurado;
• recuperação: uma vez encontrado o dado, movê-lo para alguma variável. Ao estudar as listas, as filas e as pilhas, você verá alguns comentários importantes associados a cada uma das operações. Como nosso objetivo é incentivar e desenvolver a lógica para a programação, não há sentido em se apresentar páginas com todas as operações realizadas para cada uma das estruturas. A literatura oferece esses códigos para cada uma das linguagens, e aqui não temos uma linguagem especialmente estabelecida. Assim, focaremos na lógica, no entendimento de problemas e na forma de resolvê-los.
2.4.1 Listas As listas são estruturas lineares de dados. Trazendo para o cotidiano, pense em uma lista de casamento. Ela pode apresentar diversos produtos, um em cada linha, com código, descrição e preço. Outro exemplo é uma relação das filiais de um supermercado. Veja a tabela a seguir.
Código
Nome
Ramal
001
Filial Madureira
2221
002
Filial Cascadura
2311
003
Filial Centro
3235
004
Filial Barra
4455
Tabela 5 – Lista simples (filiais de um supermercado). Fonte: Elaborada pelo autor, 2015.
Agora imagine que, ao invés de filiais, temos uma cadeia produtiva na qual um material é transformado ao longo da cadeia, a partir do centro de coleta, passando pelos centros produtivos 002 e 003 até o centro de distribuição (004): Centro de coleta (1) > Transformação (2) > Transformação (2) > Distribuição (4) > (Nulo)
O quadro que caracteriza o encadeamento apresenta, para cada filial, qual o destino para o qual ela aponta.
49
Lógica de programação
Código
Aponta para...
Dados da filial
001
002
Xxxx
002
003
Yyyy
003
004
Zzzz
004
Nulo
Wwww
Tabela 6 – Lista encadeada. Fonte: Elaborada pelo autor, 2015.
Uma lista encadeada é linear e dinâmica, composta de nós que apontam para o próximo elemento da lista. O último elemento não aponta para nenhum outro, mas sim para nulo. Para compor uma lista encadeada, basta guardar seu primeiro elemento. Veja a seguir algumas características das operações com listas.
• Inclusão: pode ocorrer no próximo lugar vazio da lista. Se, na lista, foram incluídas quatro
filiais, mas depois de um mês a 002 fechou e foi excluída, a próxima poderá ser colocada no espaço da filial 002.
• Exclusão: ao excluir um elemento, o seu espaço ficará disponível para um novo. • Alteração: é feita após a localização do elemento a ser alterado. • Ordenação:
ao ordenar uma lista, facilita-se a localização de determinado elemento. Entretanto, ao se excluir e ao se incluir um novo elemento, a lista terá de ser reordenada.
• Localização: se a lista estiver ordenada, será mais fácil encontrar o elemento procurado. Se soubermos que precisamos encontrar dois elementos e eles forem encontrados logo nos dois primeiros, o programa não precisará continuar explorando a lista até o último.
• Recuperação:
uma vez encontrado, o dado de um elemento pode ser movido para a memória, ou seja, para alguma variável.
2.4.2 Filas O que são filas? Como diferenciá-las das listas? Filas fazem parte de nossa rotina diária e servem para organizar a execução de processos. Todas têm uma capacidade de processamento e são baseadas no princípio FIFO (first in, first out), ou seja, o primeiro a chegar é o primeiro a ser atendido. Em programação, você pode compreender melhor as particularidades das filas ao verificar suas características para cada operação.
• Inclusão: o elemento deve ser inserido sempre no final da fila. • Exclusão: se houver exclusão de um elemento, sugere-se compactar a fila. Se o 002 for excluído, o 003 assume o lugar do 002, e o 004 assume o lugar do 003. O lugar do 004 fica vago par a próxima inclusão.
• Alteração: a alteração de um elemento não mudará sua posição na fila. • Ordenação: a fila deve obedecer à ordem de chegada. O primeiro a chegar é o primeiro a sair.
50 Laureate- International Universities
• Localização: a busca deverá ser em toda a fila, iniciando-se pelo primeiro que foi incluído. • Recuperação: uma vez encontrado o dado, pode-se movê-lo para alguma variável. 2.4.3 Pilhas Quem nunca empilhou livros, caixas e outros objetos? Se já passou por esta experiência, sabe que, ao empilhar, o último item colocado será o primeiro ao qual você terá acesso. Assim, diferentemente da fila, a estrutura de pilha segue o princípio LIFO (last in, first out), ou seja: último a chegar, primeiro a sair. Veja as características das operações com pilhas.
• Inclusão: o elemento deve ser inserido sempre no final da pilha. • Exclusão: se houver exclusão de um elemento, sugere-se compactar a pilha. Se o 002 foi excluído, o 003 assume o lugar do 002, e o 004 assume o lugar do 003. O lugar do 004 fica vago par a próxima inclusão.
• Alteração: a alteração de um elemento não mudará sua posição na pilha. • Ordenação: a pilha deve obedecer à ordem inversa de chegada. O último a chegar é o primeiro a sair.
• Localização: a busca deverá ser em toda pilha, iniciando-se pelo último a ser incluído. • Recuperação: uma vez encontrado o dado, deve-se movê-lo para alguma variável.
2.5 Árvores Uma árvore é uma estrutura de dados em que cada elemento tem um ou mais elementos associados. Imagine sua árvore genealógica: provavelmente, você encontrará avós, pais, filhos e netos em uma estrutura hierárquica.
Figura 4 – Grafo em árvore. Fonte: <http://www.dcc.fc.up.pt/~pribeiro/estagio2008/usaco/2_1_GraphTheory.htm>.
51
Lógica de programação
Uma árvore tem apenas uma raiz. Cada nó tem “filhos”. Os nós sem filhos de uma árvore são chamados de folhas e estão na ponta das árvores. Veja a seguir algumas características das árvores para as operações.
• Inclusão: ao incluir um elemento, ele deverá ter, obrigatoriamente, um pai. • Exclusão:
caso o elemento excluído seja “folha”, basta apagá-lo. Caso tenha filhos, entretanto, deve-se determinar se todos eles (toda a geração) também serão excluídos.
• Alteração: a alteração de um elemento não mudará sua posição na árvore. • Ordenação: na árvore, vale muito quem é filho de quem. Todo elemento, com exceção do que está no primeiro nível, terá um pai.
• Localização:
a busca deverá ser em toda árvore. Geralmente, inicia-se pelo pai, e a exploração desce a cada nível.
• Recuperação: uma vez encontrado o dado, deve-se movê-lo para alguma variável.
2.6 Grafos Grafos são a representação de elementos conectados. Geralmente são representados por círculos e arcos conectando os círculos. Se o grafo for direcionado, haverá uma seta indicando o sentido. Uma árvore é um grafo simples acíclico e conexo.
Figura 5 – Grafo não direcionado. Fonte: <http://www.dcc.fc.up.pt/~pribeiro/estagio2008/usaco/2_1_GraphTheory.htm>.
O grafo pode ser direcionado ou não direcionado. O grafo não direcionado não indica o nó de origem e o nó de destino, enquanto o direcionado, geralmente, apresenta uma seta na direção do destino.
52 Laureate- International Universities
NÓS QUEREMOS SABER! Como podemos aplicar em casos reais os nossos estudos sobre os grafos? Com o avanço das redes sociais, vários estudos vêm sendo desenvolvidos para obter indicadores nessas redes: quem está conectado com quem e quais são as pessoas mais influentes. Esses são exemplos de interesses pelas redes, que utilizam os grafos como estrutura.
53
Síntese Síntese
• Os tipos de dados podem ser numéricos, literais ou lógicos. • De
acordo com cada linguagem de programação, será utilizada uma sintaxe diferente, mas a base será a mesma: estrutura de dados, processamento e saída. E, claro, a lógica!
• Algumas
situações devem ser evitadas logo na entrada de dados. É o momento de se realizar a crítica da entrada de dados, evitando possíveis problemas futuros. Por exemplo, não se deve deixar alguém do sexo masculino ser registrado como usuário de serviços de parto, pois isso seria impossível. Porém, algumas situações exigem um cadastramento rápido, ainda sem crítica, que será realizada mais adiante.
• Algumas estruturas são extremamente úteis, pois permitem agregar dados semelhantes em
um local que passará a ser referenciado por um único nome. Assim ocorre com matrizes, vetores e registros. Cada uma dessas estruturas é formada por campos, e cada campo é definido com nome, tipo e tamanho, ficando associado à estrutura definida.
• Conhecer bem os dados é fundamental. Afinal, conforme foi apresentado, um campo que
determina distâncias pode ser indicado como inteiro ou real. Dependendo do objetivo, utilizam-se diferentes estruturas de dados para a elaboração de sistemas de informação.
54 Laureate- International Universities
Referências
Bibliográficas
BATTISTI, J. Algoritmos e lógica de programação. Disponível em: <http://www.juliobattisti. com.br/tutoriais/lista-categoria.asp?cat=0001&ast=0060>. Acesso em: 31 mar. 2015. CASTILHO, M.; SILVA F.; WEINGAERTNER, D. Algoritmos e estruturas de dados I (versão 0.7.1). Universidade Federal do Paraná, fev. 2015. Notas de Aula. Disponível em: <http://www. inf.ufpr.br/cursos/ci055/apostila.pdf >. Acesso em: 31 mar. 2015. DIJKSTRA, E. W. From my life. Disponível em: <http://www.cs.utexas.edu/users/EWD/ewd11xx/ EWD1166.PDF>. Acesso em: 31 mar. 2015. FURTADO, G. O que são vetores e matrizes (arrays)? Disponível em: <http://www.dicasdeprogramacao.com.br/o-que-sao-vetores-e-matrizes-arrays/>. Acesso em: 31 mar. 2015. ______. O que são tipos de dados primitivos? Disponível em: <http://www.dicasdeprogramacao.com.br/tipos-de-dados-primitivos/>. Acesso em: 31 mar. 2015. JAVAPROGRESSIVO . Tipos Numéricos - int (inteiro), float e double (decimais ou reais). Disponível em: <http://www.javaprogressivo.net/2012/08/java-tipos-numericos-int-inteiro-float.html>. Acesso em: 31 mar. 2015. SEBESTA, R. W. Conceitos de linguagens de programação. Tradução de José Carlos Barbosa dos Santos. 5. ed. Porto Alegre: Bookman , 2006. USA COMPUTING OLYMPIAD. Graph Theory. Disponível em: <http://www.dcc.fc.up. pt/~pribeiro/estagio2008/usaco/2_1_GraphTheory.htm>. Acesso em: 1º abr. 2015. WEV 2.0 SCIENTIFIC CALCULATOR. Disponível em: <http://web2.0calc.com/>. Acesso em: 1º abr. 2015. WIKILIVROS. Programar em C++/Entrada e saída de dados 2. Disponível em: <http:// pt.wikibooks.org/w/index.php?title=Programar_em_C%2B%2B/Entrada_e_sa%C3%ADda_de_ dados_2&oldid=256748>. Acesso em: 29 mar. 2015. XAVIER, D. W. Declaração de Variáveis. Disponível em: <http://www.tiexpert.net/ programacao/c/variaveis.php>. Acesso em: 31 mar. 2015. ______. Fluxograma e pseudocódigo. Disponível em: <http://www.tiexpert.net/programacao/algoritmo/fluxogramas-e-pseudocodigo.php>. Acesso em: 31 mar. 2015.
55
Capítulo 3 Introdução à linguagem de programação
Introdução O trecho a seguir descreve parte de um problema resolvido por empresas de marketing global. Empresas de marketing podem atuar de forma local ou global. As que atuam de forma global funcionam em determinados países, mas realizam pesquisas em outros. Quando utilizam questionários, precisam se preocupar com a língua. Afinal, uma empresa localizada nos Estados Unidos ou na Europa pode utilizar questionários para coletar informação no Brasil, na China, na Índia ou na Rússia. Nesses casos, a empresa norte-americana nem sempre poderá utilizar os questionários em inglês, pois nem todos os cidadãos desses países entendem o inglês. As empresas de marketing que atuam globalmente resolvem esses problemas contratando pessoas capazes de entender as necessidades dos norte-americanos e traduzi-las para a língua do país no qual será realizado o questionário ou a pesquisa. Se você acompanhou bem esta situação e entendeu o que acontece com as empresas de marketing, pode compreender como funcionam os compiladores. Compiladores são programas que traduzem uma sequência de comandos escritos em uma linguagem de programação (arquivo-fonte) para a linguagem de baixo nível, gerando um arquivo compilado, que executa as instruções pedidas.
Linguagem De Alto Nivel
Compilador
Linguagem Compilada
Figura 1 – Processo de compilação. Fonte: Elaborada pelo autor, 2015.
Este capítulo faz uma iniciação às linguagens de programação. O objetivo é introduzir os principais conceitos e processos relacionados com a programação, de forma que, em uma oportunidade futura, você esteja mais preparado para aprender e utilizar as linguagens de programação, construindo programas, desenvolvendo sistemas de informação. Nossa base será a linguagem C++, pois ela permite diversas abordagens. Afinal, temos sistemas em C++ funcionando em máquinas de uma fábrica e temos sistemas em C++ atuando em back office, em escritórios. Por sua versatilidade, escolhemos essa linguagem.
NÃO DEIXE DE VER... Olhar digital. O vídeo mostra como aprender a programar pode ser uma opção interessante. <https://www.youtube.com/watch?v=ZWJ3OMTQ19w>. 57
Lógica de programação
3.1 Linguagem de máquina Um computador armazena dados em estruturas que podem estar sinalizadas como ligadas ou desligadas. Assim, por meio de códigos que utilizam, por exemplo, 0 para desligado e 1 para ligado, é possível formar sequências que representam letras e outros caracteres que conhecemos. Por exemplo, as linguagens de baixo nível são formadas por instruções que correspondem quase que diretamente ao código de máquina que será enviado ao processador para execução. Por outro lado, linguagens de alto nível geralmente precisam ser compiladas antes de sua execução. Compiladores são programas que convertem os programas em linguagem de alto nível para linguagem de baixo nível. Diferentemente de uma linguagem interpretada – executada imediatamente, o processo de compilar um programa em linguagem de alto nível para linguagem de baixo nível pode tomar um tempo considerável do computador. Programas tradutores chamados compiladores convertem os programas em linguagem de alto nível para linguagem de máquina.
NÓS QUEREMOS SABER! Como ocorre o processo de compilação? Um compilador segue três passos (considerando-se o linker como sendo integrado à compilação): 1. Analisa o código e verifica a sintaxe. Se houver erro de sintaxe, a compilação é interrompida para que o programador possa corrigir esses erros e compilar novamente para procurar outros erros (compiladores não removem erros de lógica!). 2. Cria um arquivo de código-objeto com os comandos em linguagem da máquina, se erros de sintaxe não forem encontrados. 3. Cria, a partir do código-objeto, um arquivo executável, que pode funcionar independentemente do compilador.
Existem diversos compiladores para cada linguagem. Por exemplo, podemos encontrar muitos compiladores de C++ no mercado. Neste curso, podemos indicar o Dev-C++ (DEVCPP), que é gratuito e serve para as linguagens C, C++ e C#.
3.1.1 Linguagens de programação: linguagem de máquina e de baixo nível Quando os primeiros computadores foram criados, as instruções eram codificadas como dígitos numéricos. Escrever programas nesta linguagem resultava em muitos erros, com muita dificuldade para serem localizados e corrigidos. Por volta de 1940, pesquisadores desenvolveram um sistema pelo qual instruções numéricas poderiam ser representadas por mnemônicos. Assim, se desejassem realizar a seguinte operação que movia valores entre endereços de memória, ficaria assim: Mova o conteúdo do registrador 2 para o registrador 4
58 Laureate- International Universities
Em linguagem de máquina, seria expressa com algo semelhante a: 2054 Entretanto, em um sistema mnemônico, a instrução ficaria um pouco mais simples: MOV R4, R2 A partir desse sistema, montadores (assemblers, em inglês) foram desenvolvidos para converter expressões mnemônicas em linguagem de máquina. A linguagem montadora ficou conhecida como assembly. Apesar da maior facilidade em programar e entender os códigos, também havia a necessidade de serem utilizados muitos comandos para realizar uma única operação. Desse modo, alguns comandos precisavam ser compactados em um só. As linguagens com vários comandos em um só são conhecidas como linguagens de alto nível.
3.2 Linguagem de programação Como vimos no início desta unidade, a linguagem de máquina fica bem próxima da representação numérica de dados. Afinal, os dados serão armazenados no computador em estruturas que permitem ligar ou desligar. O código binário representa bem esse tipo de estrutura. Podem considerar o 0 como desligado e o 1 como ligado. O alfabeto em código binário ficaria assim:
• 01000001 = A • 01000010 = B • 01000011 = C • 01000100 = D • 01000101 = E • 01000110 = F • 01000111 = G • 01001000 = H • 01001001 = I • 01001010 = J • 01001011 = K • 01001100 = L • 01001101 = M • 01001110 = N • 01001111 = O • 01010000 = P 59
Lógica de programação
• 01010001 = Q • 01010010 = R • 01010011 = S • 01010100 = T • 01010101 = U • 01010110 = V • 01010111 = W • 01011000 = X • 01011001 = Y • 01011010 = Z Agora imagine que, para escrever o seu nome e sobrenome, seria necessário digitar uma sequência de oito dígitos para cada letra. E assim seria para comandos de atribuição de valores para variáveis. A partir dessas dificuldades, criaram-se as linguagens de mais alto nível. Gudwin (1997) apresenta um resumo interessante sobre diversas linguagens. Inicialmente surgiram as linguagens conhecidas como não estruturadas, como BASIC (Beginners All-purpose Symbolic Instruction Code) e o COBOL (COmmon Business Oriented Language), geralmente utilizados em aplicações comercias, ambos com grande divulgação na década de 1980. Mais adiante, surgiram as linguagens procedurais, “[...] pela existência de estruturas de controle, que entre outras coisas promovem o teste de condições (if-then-else), controlam a repetição de blocos de código (for, while, do), fazem a seleção de alternativas (switch, case), e dividem o código do programa em módulos chamados de funções ou procedimentos” (GUDWIN, 1997, p. 3). Exemplos destas são o Pascal (nome em homenagem ao matemático e físico Blaise Pascal), originada a partir do ALGOL no final da década de 1960 e início da década de 1970, e o FORTRAN (IBM Mathematical FORmula TRANslating system). Em 1972, foi criada a linguagem C, uma linguagem compilada, estruturada, imperativa, procedural e padronizada pela Organização Internacional de Normatização (ISO). Mais que um estilo de programação, a Orientação a Objetos (OO) é entendida de forma ampla, como um paradigma de análise, projeto e programação de sistemas de software. Vamos entender melhor sobre esse paradigma, orientação a objetos, por meio de um exemplo básico. Imagine a produção de cadeiras, bem simples.
60 Laureate- International Universities
Estado comportamento
Estado comportamento Figura 2 – Criação de objetos. Fonte: Elaborada pelo autor, 2015.
Cada cadeira tem seis partes: os quatro pés iguais, o assento e o encosto. O produtor “cria” cada um desses “objetos” com um sinal, um indicador de estado, que pode ser “colado” ou “descolado”, e cada um desses objetos no momento de criação é caracterizado como “descolado”. O encosto e o assento são parecidos: mesmo formato e cor, mas tamanhos diferentes. Os pés, com formato diferente do assento e do encosto, mas com a mesma cor. O formato do assento “recebe” uma pequena modificação: uma canaleta na parte superior e quatro furos na parte inferior. Existe um “processo” ou “evento” que fura objetos. Existe outro processo que “cava” uma canaleta em uma parte que tenha um tamanho mínimo (não é possível criar canaleta em pés de cadeira, por exemplo). Para criar uma canaleta em uma parte que tenha o tamanho mínimo, você só precisa dar as coordenadas x e y e o diâmetro do furo ou a altura, largura e profundidade da canaleta. Pronto! O assento tem furos embaixo e a canaleta em cima. Esta ação não muda o estado: todos continuam como “descolados”. Agora é preciso encaixar as peças e mudar o estado de “descolado” para “colado”. Você pode criar um objeto cola que “serve para” juntar, depois de 20 minutos, duas peças encaixadas.
Estado comportamento
Cola
Estado comportamento Figura 3 – Objeto cola criado. Fonte: Elaborada pelo autor, 2015.
61
Lógica de programação
Esse objeto “cola” muda o estado dos objetos de descolado para colado sempre que acionado. Você só precisa dizer qual objeto deve ser encaixado e em qual haverá o encaixe. Quando você encaixa o encosto no assento, segundo as regras do objeto “cola”, você tem 20 minutos para separá-los caso queira desistir. Caso contrário, após 20 minutos estarão colados. Note que ocorreram modificações no tempo (20 minutos) e físicas (aproximação de objetos). Mas, se ao invés de indicar o par “encosto/assento”, você indicar o par “assento/pé”, o objeto “cola” juntará assento e pé. Claro, em 20 minutos.
Figura 4 – Cadeira após o procedimento “colagem”. Fonte: Elaborada pelo autor, 2015.
Como visto no exemplo, esse paradigma considera a composição e interação entre diversas unidades de software chamadas de objetos. Quando programamos de forma orientada, existirão objetos formados por componentes de objetos, e os componentes, assim como cada objeto, poderão apresentar ou mudar qualidades (estados) e realizar ações (comportamentos). A interação entre objetos ou outros fatores, como o passar do tempo, podem alterar esses estados e iniciar atividades, mudar comportamentos. Na programação orientada a objetos, um conjunto de classes é implementado para definir os objetos. Cada uma das classes vai definir estados possíveis (atributos) e comportamentos (métodos) dos objetos, bem como o relacionamento entre os objetos com outros objetos. Alguns exemplos de linguagens com suporte e orientação a objetos são: C++, C#, Java, Object Pascal, Objective-C, VB.NET, Python, SuperCollider, Ruby e Smalltalk. Pensando em programação para uso na internet e que utilizam esse paradigma, temos ActionScript, ColdFusion, Javascript, PHP (a partir da versão 4.0), Perl (a partir da versão 5) e Visual Basic (a partir da versão 4). Entre as linguagens orientadas a objetos, as consideradas como mais modernas são Java, C#, C++, Object Pascal (Delphi), Ruby, Python. As linguagens Smalltalk, Self e IO são consideradas como totalmente orientadas a objetos. C++ adota o paradigma da orientação a objetos (POO) apenas parcialmente e também aceita o antigo modelo procedural de programação. Podemos usar POO, mas a linguagem não força o programador a adotar esse paradigma de programação (WIKILIVROS, 2015). Um resumo dos principais paradigmas de programação foi apresentado por Silva (2006). 62 Laureate- International Universities
1. Imperativo. Nesse caso, segundo Silva (2006), os programas são centrados no conceito de um estado (modelado por variáveis). Existem, também, as ações (comandos), que manipulam o estado. Muitos reconhecem esse tipo de paradigma como procedural –, afinal ele é composto de subrotinas ou procedimentos como mecanismo de estruturação. Alguns exemplos são: Fortran, Pascal e “C”. 2. Orientação a objetos (OO). Esse paradigma é considerado por muitos profissionais como uma subclassificação do imperativo. Silva (2006) expõe que uma aplicação é estruturada em módulos (classes) que agrupam estados (atributos) e operações (métodos). As classes já existentes podem ser estendidas e/ou usadas como tipos (cujos elementos são objetos). Como exemplos, temos Smalltalk, “C++” e Java. 3. Funcional. Nesse caso, o autor indica que os programas são funções que descrevem uma relação explícita e precisa entre entrada e saída (E/S). Com conceitos sofisticados como polimorfismo, funções de alta ordem e avaliação sob demanda, é usada em prototipação e Inteligência Artificial. Por exemplo, temos LISP. 4. Programação em Lógica. Para Silva (2006), nesse caso, os programas são relações entre E/S. Esse tipo de programação apresenta um estilo declarativo, como no paradigma funcional. Inclui características imperativas, por questão de eficiência. Esse paradigma é utilizado em aplicações de bancos de dados e sistemas especialistas e um exemplo é Prolog. Esses são os paradigmas mais conhecidos, mas você também pode encontrar, em termos de programação, outros termos como a programação orientada a aspectos, orientada a eventos, orientada a regras etc.
3.2.1 Funções As linguagens de programação em geral utilizam variáveis e constantes e em grande parte delas programadores criam e usam funções. O que é uma função? Vamos estudar um exemplo: Função – VENDER TICKET NA BILHETERIA DO TEATRO Quem executa – a pessoa que trabalha na bilheteria SAÍDA – Qual é o produto-final, a saída desse processo – Os tickets entregues de acordo com o pedido e com o pagamento do cliente. ENTRADA – Pedido do cliente, informando o LOCAL ou os ASSENTOS desejados. O PROCESSO – A pessoa que trabalha na bilheteria...
• identifica no mapa ou imagina a localização dos assentos desejados; • identifica o valor unitário para aqueles assentos; • informa o valor; •
realiza o pagamento (note que esse procedimento pode ser uma nova função, com várias ações);
• destaca os tickets; • faz uma marca em cada ticket; • entrega os tickets.
63
Lógica de programação
Agora vamos entender as funções em uma linguagem, por exemplo, C. Funções podem ser definidas como um conjunto de comandos agrupados em um bloco que recebe um nome e através deste pode ser ativado. Geralmente existem dois locais nos programas em que aparecem as funções:
• local onde a função é chamada; • local onde a função é declarada (ou definida). Local onde a função é chamada: dentro do programa principal ou dentro de outro módulo (que até pode ser outra função, veja o exemplo anterior, no pagamento), pode haver a necessidade de se executar um conjunto de comandos para se obter determinado valor. Nesse local, chama-se (ou invoca-se) a função. Local onde a função é definida: em outro local, a função é definida – ali encontram-se o nome, os parâmetros de entrada e os comandos que compõem a função. Qual a vantagem? As funções separam o programa em partes (blocos), que podem ser logicamente compreendidos de forma isolada. Assim, permitem o reaproveitamento de código já construído (por você ou por outros programadores); além disso, funções evitam que um trecho de código que seja repetido várias vezes dentro de um mesmo programa, deixando o programa mais fácil de ser analisado. Uma alteração de código fica mais simplificada uma vez que é realizada apenas dentro da função que se deseja. Veja o exemplo que compara o número de um assento desejado com um único assento existente, disponível. Note que nesse caso o valor que retorna é um inteiro (int), e os valores comparados também. O programa também indica se o número do assento desejado é maior ou menor que o disponível, retornando 1 ou 2.
int compara_assentos(int desejado, int assento) { if (desejado == assento) return (0); else if (desejado > assento) return (1); else if (desejado < assento) return (2); } Quadro 1 – Código para comparar assentos. Fonte: Elaborado pelo autor, 2015.
64 Laureate- International Universities
3.2.2 Bibliotecas Uma biblioteca é compreendida como um arquivo que contém várias funções agrupadas. Por exemplo, a linguagem C++ possui uma biblioteca padrão (standard, std) com muitas funções, e esta se divide em várias bibliotecas ou arquivos menores de acordo com os tipos de função que cada um contém. Ao programar em C++, você pode utilizar diversas bibliotecas que permitirão desenvolver com mais agilidade: por exemplo, “cmath” é uma biblioteca que oferece funções matemáticas no padrão da linguagem C. Se utilizar “string”, o programador contará com diversas funções da biblioteca padrão de C++ para tratar cadeia de caracteres. O código de uma biblioteca pode ser expandido em um programa por meio de uma importação. A importação de uma biblioteca ocorre pela diretiva INCLUDE (incluir) seguido do nome da biblioteca entre os sinais de menor (<) e maior (>). A diretiva “#include” expande o código fonte da biblioteca para dentro do programa que será compilado. Ou seja, lembremos que o processo envolve escrever o código, compilar e executar. Durante a pré-compilação, o código da biblioteca é incluído no programa, quando o compilador encontra o #include. O caracter sharp (#) deve estar logo no início da linha e deve ser usado no início da programação, para ser reconhecido pelo pré-processador, antes da compilação. Conheça algumas bibliotecas-padrão da linguagem C:
• Funções matemáticas:
#include <cmath>
• Funções de string:
#include <cstring>
• Funções de string do C++:
#include <string>
• Funções de I/O: (entrada;saída)
#include <cstdio>
• Funções de tempo:
#include <ctime>
Lembre-se que, apesar de seguir esses conceitos genéricos, a forma de uso de bibliotecas pode variar de linguagem para linguagem. Por exemplo, em algumas linguagens o nome da biblioteca pode precisar do nome completo do arquivo, incluindo a extensão. Veja a diferença: #include <stdlib.h>
- biblioteca de C
#include <iostream>
- biblioteca de C++
3.2.3 Lógica, Linguagens de Programação e Internet Este curso aborda a Lógica em Linguagens de programação. Mais do que conhecer a sintaxe de uma linguagem, importante é saber como utilizá-la. Por exemplo, se me oferecerem alguns instrumentos utilizados por um mecânico de automóvel e pedirem para eu retirar um motor, certamente eu não saberei fazer. O mecânico “sabe o algoritmo”, conhece a lógica, entende como funciona o processo de desmonte de um motor! Provavelmente se ele ler um manual de um automóvel de outra marca, aprenderá como fazer um mesmo procedimento que ele já fez no seu próprio automóvel anteriormente. Por essa razão, nesse momento, não estamos programando, porém estamos explorando conceitos e aspectos importantes para a lógica de programação que poderá facilitar a aprendizagem da programação. 65
Lógica de programação
Algumas linguagens tornaram-se populares para uso de sistemas na internet. Nesta seção, apresentaremos alguns exemplos que poderão servir como motivação para aprofundamento, no futuro. Selecionamos algumas linguagens e destacamos alguns aspectos importantes. O objetivo não é listar todas as linguagens existentes, mas apresentar características de algumas, que podem servir como fundamentação do seu conhecimento e para o aprofundamento de seus estudos em alguma linguagem específica. Antes de aprofundarmos em programação, vamos entender o acesso à internet. O acesso à internet
Pense na internet da seguinte forma: Um ou mais computadores-servidores.
Figura 5 – Figuras de servidores – computadores. Fonte: Biblioteca de figuras do MS Word.
Em uma explicação bem simplificada, o acesso à internet ocorre da seguinte forma: existem dispositivos que acessam dados, aplicativos e páginas armazenados nos servidores. Esse acesso não ocorre diretamente, mas via computadores conectados em uma imensa rede, a internet. Você envia o endereço-final (o endereço da página ou aplicativo que está no servidor) e não sabe (e nem percebe) a rota que será utilizada para o tráfego dos dados. No final do processo, você fez um envio de dados e recebeu a resposta – uma tela, uma página, um documento – em seu dispositivo (telefone, tablet, notebook, computador de mesa etc.).
Acesso Figura 6 – Tablets, celulares, notebooks e CPU. Fonte: Biblioteca de figuras do MS Word.
HTML, Linguagem de Marcação de Hipertexto (Hipertext Markup Language) não é considerada uma linguagem de programação, mas uma linguagem de marcação. Assim, em um texto que aparece em páginas escritas em HTML, como “estou em negrito”, na verdade está escrito no código original como <b> estou em negrito </b>. “<b>” indicará ao navegador (Internet Explorer, Firefox, Chrome etc.) que o que vier depois desta marcação (“<b>”) ficará em negrito (bold, em inglês), até que se encontre o final da marcação, que geralmente inicia com “/”, nesse 66 Laureate- International Universities
caso “</b>”. Lembre-se que, para essa marcação funcionar, é obrigatório que o navegador reconheça o tipo de documento como sendo uma página HTML, e para isso existem também as marcações que indicam isso, ou seja <html> com </html> para indicar o início e fim da página, e <body> com </body> para indicar o corpo da página HTML e que vai conter grande parte do conteúdo. <input > </input> é uma marcação que permite entradada de dados por parte do usuário e <button> apresenta um botão que pode iniciar a execução de uma função quando clicado. Outra marcação interessante é <script> e </script>, que permite a inclusão de um script, como comandos em Javascript, como veremos no próximo exemplo. Javascript (não confunda com Java) é uma linguagem criada em meados dos anos 1990 para realizar algumas tarefas em sistemas que acessavam a internet a partir de computadores instalados do lado do “cliente” (na verdade, quando acessamos a internet, fazemos a partir de um dispositivo “cliente”. Na época, scripts (sequência de comandos) eram executados do lado do computador cliente, sem a necessidade de acesso ao servidor (o computador principal, acessado via internet). Geralmente o script é inserido no meio da linguagem de marcação, como as utilizadas para gerar páginas na internet. Veja um exemplo a seguir.
<!DOCTYPE html> <html> <body> <h1>JavaScript pode validar entrada de dados</h1> <p>Digite um número entre 1 e 10:</p> <input id=”numb” type=”number”> <button type=”button” onclick=”myFunction()”>Executa </button> <p id=”demo”></p> <script>
function myFunction() { var x, text; // Recebe o valor digitado com a variável id=”numb” x = document.getElementById(“numb”).value; // Se x não for um número ou (||) se for menor que 1 ou(||) maior que 10 if (isNaN(x) || x < 1 || x > 10) { text = “Entrada não é válida”; } else { text = “Entrada OK”; } document.getElementById(“demo”).innerHTML = text; } </script>
</body> </html> Quadros 2 e 3 – Função Javascript para validar dados. Fonte: Elaborado pelo autor, 2015.
67
Lógica de programação
Neste momento não estamos preocupados com a linguagem e os comandos desconhecidos, mas sim com a inserção da marcação <script>. Note que inserir o javascript na página HTML torna a página interativa. Agora você pode acessar esse mesmo script e alterá-lo conforme o exemplo anterior e testar. Acesse em: <http://www.w3schools.com/js/tryit.asp?filename=tryjs_intro_validate>. Muitos profissionais não consideram o ASP (de Active Server Pages) como uma linguagem de programação, mas como uma estrutura de bibliotecas básicas que permite o processamento por linguagens de script no computador que atua como servidor, gerando conteúdo dinâmico na web. Alguns exemplos de linguagens aceitas: VBScript, JScript, PerlScript, Tcl ou Python. As duas primeiras são suportadas por padrão. Como vimos, linguagens Javascript e o VBScript podem ser processadas pelo navegador do visitante. ASP é processado pelo servidor, a partir de chamadas de páginas em HTML, por exemplo. ASP permite executar consultas a Banco de Dados usando uma biblioteca de componentes, ActiveX, e gerar uma saída apresentada na tela do navegador, por exemplo. PHP é o acrônimo (recursivo) para “PHP: Hypertext Preprocessor”, ou seja, pré-processador para hipertexto. Essa linguagem é muito utilizada para o desenvolvimento web e é considerada por alguns como concorrente de ASP. Uma página em PHP em geral tem extensão “php” e contém também o código HTML. O PHP será processado no servidor, por isso o PHP é conhecido como linguagem “server-side”. Se o código PHP fica no servidor, os programas não ficam disponíveis para acesso, como no Javascript, por exemplo. Apenas o resultado, após o processamento, vai para o navegador. Veja um exemplo armazenado em um servidor de internet. Note que você não poderá executar esse script em seu computador a não ser que você instale um ambiente que simule um servidor ou que ele seja um servidor. Na tabela a seguir está o código do arquivo que tem extensão “php”, e o resultado que vai aparecer na tela do computador-cliente é apresentado em seguida.
<!DOCTYPE html> <html> <body> <?php $x = 1; while($x <= 5) { echo “Numero: $x <br>”; $x++; } ?> </body> </html> Quadro 4 – Código em PHP dentro da página HTML. Fonte: Elaborado pelo autor, 2015.
Note que “<?php” e ?> definem o trecho de código que deve ser executado em PHP. $x é a variável utilizada no script, inicia com 1 e termina com 6 (sim, porque depois de imprimir o “Numero: 5”, a variável $x é acrescida de 1 e sai do loop, certo?).
68 Laureate- International Universities
O resultado que aparece na tela do computador que acessou a página de internet fica assim: Numero: Numero: Numero: Numero: Numero:
1 2 3 4 5
Alguns exemplos de sistemas desenvolvidos em PHP são o Wordpress e a Wikipedia. JAVA – A linguagem Java foi criada nos primeiros anos da década de 1990. Desenvolvida a partir do C++, seu objetivo era executar o mesmo programa em múltiplas plataformas de hardware e software sem precisar modificá-lo, adaptá-lo aos ambientes. Esse conceito de plataforma – ambiente com diversas ferramentas para aplicações – também foi utilizado pela Microsoft quando criou a plataforma.NET. De acordo com Gudwin (1997), Java é formada por bytecodes. O autor explica: O Java é uma linguagem parcialmente compilada e parcialmente interpretada. Um compilador Java transforma o programa fonte, escrito em Java, em arquivos-objeto chamados bytecodes. Esses bytecodes precisam ser executados então por interpretadores Java que são desenvolvidos para cada plataforma de hardware/software. Os bytecodes podem ser basicamente de dois tipos. O primeiro tipo tem acesso completo à máquina, ou seja, é capaz de manipular a memória, o console e o sistema de arquivos. Programas desse tipo são chamadas de aplicações Java. O segundo tipo de bytecode sofre uma série de restrições quanto ao acesso de memória, console e sistema de arquivos. Essas restrições são colocadas em nome da segurança, visto que seu destino é a elaboração de programas que serão distribuídos pela Internet, e por isso não provém de fonte conhecida ou confiável. Esses bytecodes são chamados de Java applets. (GUDWIN, 1997, p. 9).
VOCÊ O CONHECE? James Gosling nasceu em 1955 no Canadá. Ele é conhecido como o pai da lingua-
gem de programação Java. Em 1977, se graduou em ciência da computação pela Universidade de Calgary e concluiu o doutorado na mesma área, em 1983, pela Universidade Carnegie Mellon. Durante o doutorado, produziu o editor de texto emacs para UNIX, e antes da parceria com a Sun Microsystems ele desenvolveu vários compiladores e sistemas de mensagens eletrônicas.
A documentação para uso do Java EE (Oracle, 2012) apresenta as quatro plataformas de linguagem de programação Java:
• Java Platform, Standard Edition (Java SE); • Java Platform, Enterprise Edition (Java EE); • Java Platform, Micro Edition (Java ME); • JavaFX. Segundo o documento, todas as plataformas Java consistem de uma Java Virtual Machine (VM) e Uma Interface de Programação de Aplicativo (API).
69
Lógica de programação
NÓS QUEREMOS SABER! O que é uma Maquina Virtual Java? E uma API? O Java Virtual Machine é um programa, para determinada plataforma de hardware e software que roda aplicativos em Java. Uma API é uma coleção de componentes de software que você pode usar para criar outros componentes ou aplicativos de software.
Cada plataforma Java fornece uma máquina virtual e uma API, e isso permite que aplicativos escritos para essa plataforma possam rodar em qualquer sistema compatível com todas as vantagens da linguagem de programação Java: plataforma de independência, o poder, a estabilidade, facilidade de desenvolvimento, e segurança. Java SE - API do Java SE fornece a funcionalidade principal da linguagem de programação Java.
Ele define tudo, desde os tipos básicos e objetos da linguagem de programação Java para as classes de alto nível que são usados para redes, segurança, acesso à base de dados, interface gráfica do usuário (GUI) de desenvolvimento e de análise de XML. Além da API do núcleo, a plataforma Java SE consiste de tecnologias de implantação de uma máquina virtual, ferramentas de desenvolvimento e outras bibliotecas de classes e kits de ferramentas comumente usados em aplicações da tecnologia Java. Java EE - A plataforma Java EE é construído em cima da plataforma Java SE. A plataforma Java
EE fornece um ambiente de tempo de execução e API para desenvolvimento e execução de grande escala, multicamadas, aplicações de rede escaláveis, confiáveis e seguras. Java ME - A plataforma Java ME fornece uma API e uma máquina virtual de pequena pegada
para executar aplicações de linguagem de programação Java em pequenos dispositivos, como telefones celulares. A API é um subconjunto da API do Java SE, juntamente com bibliotecas de classes especiais úteis para o desenvolvimento de pequenas aplicações do dispositivo. Aplicações Java ME são muitas vezes os clientes de serviços de plataforma Java EE. JavaFX - JavaFX é uma plataforma para a criação de aplicações ricas para internet usando uma
API de interface do usuário leve. Aplicativos JavaFX usa gráficos acelerados por hardware e mecanismos de mídia para tirar proveito de clientes de alto desempenho e um moderno look-andfeel, bem como APIs de alto nível para conexão com fontes de dados em rede. Aplicativos JavaFX podem ser clientes de serviços de plataforma Java EE. Desenvolvedores utilizam o JDK: o Java Development Kit, em português, Kit de Desenvolvimento Java, contém vários utilitários voltados ao desenvolvimento para a plataforma Java e também compilador e bibliotecas. Usuários utilizam o JRE: para as aplicações Java rodarem é necessário existir um ambiente de execução, o JRE – um pacote de software contendo a máquina virtual e a biblioteca de classes.
70 Laureate- International Universities
NÓS QUEREMOS SABER! Quais as vantagens das classes de bibliotecas? As classes de bibliotecas servem para simplificar e otimizar sequência de códigos produzida pelos programadores. Como em outras linguagens, em Java uma biblioteca pode conter funções (na verdade sequência de códigos, trechos de programas). Essas funções realizam tarefas muito utilizadas e comuns aos programas, como tratamento de arquivos (conexão, abertura, fechamento), operações com listas de elementos ou manipulação de sequência de caracteres (strings). As bibliotecas podem facilitar a comunicação entre o aplicativo e o sistema operacional. Por exemplo, as bibliotecas java.io implementam o código internamente para trabalhar com arquivos de entrada e saída (Input e Output – I/O).
Uma desvantagem de Java apontada por alguns programadores é que a pré-compilação leva algum tempo, ou seja, antes de gerar o programa executável, leva-se um pouco mais de tempo. Não é um grande problema quando se utilizam grandes servidores, mas programadores com computadores pessoais podem “sentir” esse tempo de alguma forma.
NÃO DEIXE DE LER... Conheça a linguagem Prolog, que é uma linguagem declarativa e sem estruturas de controle (if-else, do-while, for, switch). A linguagem utiliza métodos lógicos para declarar como o programa deverá atingir o seu objetivo. Veja mais em: <http://www. linhadecodigo.com.br/artigo/1697/descobrindo-o-prolog.aspx>.
Para otimizar o trabalho de desenvolvimento, programadores utilizam ambientes Integrated Development Environment (IDE) – em português, Ambiente Integrado de Desenvolvimento. Trata-se de um software com ferramentas de apoio ao desenvolvimento. Ambientes IDE geralmente apresentam:
• editor para o código-fonte do programa; • compilador (compiler) – compila o código-fonte do programa, aponta os erros e depois de corrigidos gera a linguagem de máquina;
• linker – liga (linka) o código com bibliotecas gerando o programa executável; • depurador (debugger) – que auxilia encontrando erros, destacando-os em cores, sugerindo mudanças e correções;
• modelagem (modeling) – criação em um modelo, muitas vezes visual, com classes, objetos, interfaces, associações e interações;
• geração
de código – a partir de exemplos e modelos comumente utilizados, ganhando tempo no processo de desenvolvimento e distribuição do software;
• distribuição (deploy) – que facilita a criação de um instalador de software;
71
Lógica de programação
• testes automatizados (automated tests) – realiza testes com base em regras ou programas de testes previamente especificados, gerando um relatório;
• refatoração (refactoring) – otimiza o código, deixando-o mais limpo fácil de entender. Alguns exemplos de IDE: BlueJ – através de uma interface visual e com alguns recursos que melhoram o aprendizado
inicial, gera o código Java, facilitando o entendimento de Java e do paradigma de Orientação a Objetos. Orientação a Objetos; DEV-C++, Code::Blocks, Turbo C – são aplicativos que geram código para C e C++; Eclipse – gera código em linguagem Java. Por meio de plugins – estruturas adicionais – o Eclipse
suporta diversas linguagens, por exemplo, o Python e C/C++); Genexus – ferramenta que gera código em diversas linguagens de programação, utiliza bancos
de dados e é baseado em conhecimento; Netbeans – gera código em linguagem Java e também suporta diversas linguagens como Python
e C/C++; Sun Studio – trabalha com linguagens C, C++ e Fortran; Visual Studio .NET – gera código para Framework .NET, da Microsofor, em Visual Basic .NET,
C#, C++, J# e outras compatíveis com .NET.
NÃO DEIXE DE LER... Alguns sistemas podem ajudar a aprender Java. Um deles é o BlueJ. BlueJ é um ambiente de desenvolvimento Java projetado especificamente para o ensino em um nível introdutório. O BlueJ foi projetado e implementado pelas equipes das universidade Monash University, Melbourne, Australia e The University of Southern Denmark, Odense. Maiores informações sobre BlueJ estão disponíveis no site oficial (<http://www.bluej.org>).
Padrões de projeto, ou Design pattern, são soluções encontradas, para problemas conhecidos e frequentes. Uma solução genérica pode ser reutilizada para um problema em determinada situação semelhante a outras, no contexto de desenvolvimento de software. Um padrão de projeto acaba por ser transformado em código fonte ou de máquina. São identificados três tipos de padrões.
• Padrões de criação: estão associados com a criação de objetos. • Padrões estruturais: tratam das estruturas, relações entre classes e objetos. • Padrões
comportamentais: tratam de comportamento, ou seja, de interações e das responsabilidades associadas às relações entre classes ou objetos.
Vejamos um exemplo: Padrão Singleton Usando o paradigma de Orientação a Objetos (OO), uma instância é um caso, uma amostra. Veja os quatro pés da figura a seguir. 72 Laureate- International Universities
Estado comportamento
Estado comportamento Figura 7 – Criação de uma cadeira, com estados e comportamentos. Fonte: Elaborada pelo autor, 2015.
Como no exemplo da cadeira, durante a sua criação, cada pé da cadeira é uma instância de um “modelo”, “uma forma” de pés, que em OO entendemos como “classe”, que tem uma cor e um tamanho. Cada pé é uma instância da classe pé-de-cadeira, por exemplo. Cada uma das quatro instâncias da classe pé-de-cadeira tem cor preta e mede 40 cm. Algumas classes devem ser instanciadas uma única vez: um spooler de impressão armazena uma fila de documentos para serem impressos, gerencia uma única fila; um sistema de arquivos, um gerenciador de janelas, um objeto que contém a configuração de um programa. Todos esses exemplos funcionam de forma única. Diferentemente dos pés da cadeira, que podem existir várias vezes, um sistema contém apenas um gerenciador de janelas, um gerenciador de fila de impressão. No exemplo da cadeira, uma cadeira contém somente um assento e um encosto.
NÃO DEIXE DE LER... DA ROCHA, Helder. Padrões de Design com aplicações em Java. Curso J930: DesignPatterns Versão 2.1 Argonavis. Disponível em; <http://www.argonavis.com.br/cursos/java/j930/tutorial/Design_Patterns.pdf >. Acesso em: 4 abr. 2015. Livro: GAMMA, Erich. Padrões de Projetos: Soluções Reutilizáveis. Bookman, 2007.
3.2.4 A lógica do E e do OU Em muitas situações, em momentos variados, podemos utilizar OU ou E sem considerar uma lógica. Porém, em programação isso funciona diferente. Em se tratando de lógica de programação, ao estabelecer uma condição dizendo que você vai construir um prédio OU uma casa, você terá três possibilidades que indicam a condição como verdadeira: você pode construir somente a casa, somente o prédio ou pode construir os dois. Se você disser que vai construir um prédio “E” uma casa, se você construir somente um dos dois, a sua proposta não será entendida como realizada “de verdade”. Ou seja, quando se usa o “E” em uma expressão, todas as condições devem ser satisfeitas para que essa combinação de possi73
Lógica de programação
bilidades seja verdadeira. Diferentemente, se você utiliza “OU”, basta apenas uma condição ser satisfeita para que a sentença seja verdadeira.
3.2.5 Dicas e máximas sobre problemas e a programação A curva de aprendizado da programação geralmente resulta em otimização do processo de desenvolvimento. Com o tempo, alguns atalhos podem ser seguidos, assim como boas práticas. Schultz (2003, p. 17) apresenta alguns procedimentos para a construção de bons algoritmos e, consequentemente, bons programas: • Ler atentamente o enunciado • Retirar do enunciado a relação das entradas de dados • Definir a relação das saídas • Determinar o que deve ser feito para transformar entradas determinadas nas saídas especificadas • Construir o algoritmo • Executar o algoritmo (teste de mesa)
Schultz (2003, p. 17) também apresenta algumas “máximas de programação”: • Algoritmos devem ser feitos para serem lidos por seres humanos • Escreva comentários no momento em que estiver escrevendo o algoritmo • Os comentários deverão acrescentar alguma coisa • Use comentários no prólogo (o que faz o algoritmo, como utilizá-lo, explicar o significado das variáveis mais importantes autor, data de escrita e alterações) • Utilize espaços em branco para melhorar a legibilidade • Escolha nomes representativos para suas variáveis • Um comando por linha é suficiente • Utilize parênteses para aumentar a legibilidade das expressões e prevenir-se contra erros. • Utilize “endentação” para mostrar a estrutura lógica do algoritmo”
74 Laureate- International Universities
Síntese Síntese
• Neste capítulo, tivemos acesso a elementos introdutórios à programação e às linguagens
de programação. O computador trabalha com linguagem de máquina, baseada em sensores que podem indicar dois tipos de estado: ligado e desligado.
• Combina-se
essas duas possibilidades diversas vezes, de forma que consigamos representar, por exemplo, letras, palavras e comandos, que podem ser interpretados.
• Compiladores interpretam e geram códigos mais amigáveis para as máquinas; linkeditores podem agregar outros programas e um programa executável é gerado.
• As
linguagens para internet podem funcionar em máquinas clientes ou nos servidores. Além disso, existem várias linguagens que são interpretadas pelos navegadores.
• Independentemente
da linguagem, haverá sempre determinados elementos: problemas, entrada, saída, processamento.
• Para que o processo seja realizado, precisaremos declarar e utilizar variáveis e desenvolver funções ou objetos, dependendo do paradigma adotado.
• Enfim, a lógica é um elemento fundamental que pode variar de acordo com a linguagem adotada, mas que contém características utilizáveis em todas as linguagens.
75
Referências Bibliográficas
DEITEL, H. M. Deitel, P. J.. C++: como programar. 5. ed. São Paulo: Pearson Prentice Hall, 2006. GUDWIN, R. R. Linguagens de programação. Notas de aula para a disciplina EA877. Mini e Microcomputadores: Software Campinas: DCA/FEEC/UNICAMP (1997). Disponível em: <ftp:// ftp.dca.fee.unicamp.br/pub/docs/ea877/lingpro.pdf >. Acesso em: 2 abr. 2015. SCHULTZ, M. R. de O. Metodologias para ensino de lógica de programação de computadores. Monografia. Programa de pós-graduação em ciência da computação. Florianópolis, novembro de 2003. SILVA, E. M. Paradigmas de Programação. Aula I, Apresentação. Unicerto Faculdades. 2006. Disponível em: <http://edilms.eti.br/uploads/file/pp/PP-aula-01-apresentacao.pdf>. Acesso: 25 maio 2015. WIKILIVROS. Programação orientada a objetos/introdução. Disponível em: < h t t p : / / p t . w i k i b o o k s . o r g / w i k i / Pr o g r a m a % C 3 % A 7 % C 3 % A 3 o _ O r i e n t a d a _ a _ O b j e t o s / Introdu%C3%A7%C3%A3o>. Acesso em: 25 maio 2015.
76 Laureate- International Universities
Capítulo 4 Linguagem de programação: estruturas condicionais e de repetição
Introdução Todos os dias, acordamos e iniciamos uma série de ações em sequência e que muitas vezes passam despercebidas. Muitos movimentos que fazemos são repetidos: por exemplo, ao andar, você repete movimentos com as pernas; nem sempre percebe, mas seus braços se movem também. A pessoa caminha até chegar ao seu destino. Ou seja, o movimento das pernas se repete até certo momento. Pensemos em outro exemplo, agora relacionado à alimentação. Ao colocar um alimento na boca, uma pessoa inicia a mastigação. Quantas vezes ela mastiga? Geralmente não contamos quantas vezes mastigamos, mas sabemos que a maior parte das pessoas mastiga até o momento em que percebem que podem engolir o alimento. Assim, percebemos novamente a repetição, sempre dependente de um sistema de controle, uma condição que faz com que essa repetição seja interrompida. Apesar de já terem sido apresentadas em alguns exemplos anteriores com menor ênfase, neste capítulo, teremos três objetivos a serem alcançados, desta vez com mais profundidade: conhecer e aplicar estruturas condicionais, conhecer e aplicar estruturas de repetição e elaborar algoritmos para a solução de problemas. A lógica de programação depende profundamente desses três temas. Ao final deste capítulo, provavelmente você estará bem mais alerta e perceberá que a lógica de programação pode ser aplicada em sistemas de informação, e não somente a sistemas e programas de computador. Afinal, a informação está presente dentro e fora dos computadores.
4.1 Estruturas condicionais Durante a prática profissional, é comum tomarmos decisões. Precisamos decidir o tempo todo. Muitas vezes, a decisão implica decisões simples, com duas alternativas: sim ou não. Vou a um destino de carro ou não? Em outras situações, a questão envolve mais de uma decisão. Ok, não vou de carro. Então vou de ônibus ou vou de metrô? E se for de ônibus, vou preferir a linha A1 ou a linha B2? E se houver 10 lugares vazios, em qual sentarei? Como vimos, decisões podem apresentar duas alternativas, podem apresentar mais de duas alternativas, podem gerar novas decisões a serem tomadas. Programas de computador também precisam tomar decisões. E as decisões devem ser programadas. Uma forma de visualizar a lógica programada para a execução de uma determinada rotina é utilizar fluxogramas. Os fluxogramas, em geral, utilizam os símbolos conforme a Figura 1. No entanto, você pode encontrar algumas variações e até mesmo omissões (por exemplo, é comum encontrar bancos de dados em caixas retangulares, o que ficaria fora da representação genérica). 77
Lógica de programação
Início ou fim do programa
Conector, se houver continuação em diferentes partes do fluxo
Decisão: Desvios conforme determinada condição
Linhas que indicam a direção do fluxo
Processamento, alteração em conteúdo de variáveis, etc.
Operação ou ajuste manual no processo
Abertura ou fechamento de arquivos Subrotina: execução de subrotina
Estrutura de armazenamento de dados. Banco de dados. Geralmente conectado a operações para inserir, alterar, consultar e excluir.
Dados: entrada ou saída
Espera. Aguarda por determinado período ou por alguma ação.
Figura 1 – Estrutura genérica para representação de fluxogramas. Fonte: Chamovitz, 2015.
Vamos utilizar fluxogramas para representar ações, repetição e decisões. Para programar as decisões, é preciso: 1. saber quais são as regras da decisão; 2. saber se existem dependências ou exceções. Ora, é claro que, se um programador vai criar um programa, ele precisa saber as regras para colocá-las no código. Isso é simples (e lógico!). Quem cria as regras, porém, são seres humanos, com todas as suas interpretações e complexidades. Muitas vezes, programadores e usuários (ou stakeholders) não conhecem todas as regras antes de o programa começar a funcionar. Em outras, mesmo com a execução do programa já implementada, percebe-se que uma das regras pode estar incompleta ou que se criaram novas regras, e o programa pode apresentar erros. É o que veremos no estudo de caso a seguir.
Mudanças em estruturas condicionais Um programador decide implementar, dentro de um código, uma matriz com todos os estados brasileiros e mais o Distrito Federal. Sua intenção é muito boa, já que, segundo o seu pensamento, vai poupar tempo durante a digitação, quando o digitador precisar apenas escolher entre 28 alternativas (27 unidades federativas e mais o Distrito Federal), que aparecem em ordem alfabética. O sistema conta, ainda, com um dispositivo que permite localizar facilmente a partir da digitação na caixa de texto que aparece acima da tabela. A tela ficou bem parecida com diversas telas que apresentam, em entrada de dados, as unidades federativas que compõem sistemas de abrangência nacional. Para ilustrar, mostramos uma tela semelhante à obtida pelo programador.
78 Laureate- International Universities
Figura 2 – Exemplo de interface com nomes de estados utilizada por sistemas de abrangência nacional. Fonte: Adaptado de http://tabnet.datasus.gov.br/cgi/deftohtm.exe?sih/cnv/nruf.def.
Naquela ocasião, o programador foi homenageado, pois a alteração permitiu a economia de tempo e custo com mão de obra, reduziu erros de digitação e motivou colegas. A regra era clara: cada um dos mais de 200 programas de computador deveria ser revisto e, se necessário, o código que testava as unidades federativas deveria ser incluído nos programas-fonte. Não foi criada uma tabela. O código era inserido internamente ao programa e testava cada uma das unidades: IF uf = “Acre” Then xxxxxx ; IF uf = “Amazonas” Then xxxxxx ; IF uf = “Amapá” Then xxxxxx ; … IF uf = YYY Then xxxxxx ;
O sistema funcionava muito bem, todos estavam satisfeitos. Entretanto, não foi pensada a possibilidade de criação de uma nova unidade federativa. Em 2011, houve a rejeição para a criação de duas novas propostas de criação de unidades federativas (GASPARIN, 2011). Os resultados poderiam ser outros, como a criação de novas unidades federativas.
79
Lógica de programação
Agora, imagine que o código anterior estivesse espalhado por dezenas de programas e que, por algum motivo, um programa não tivesse sido alterado. Veja o esquema a seguir:
• Entrada de dados esperada: Acre, Amazonas, Amapá.... • Entrada de dados real: Acre, Amazonas, Amapá.... Nova unidade a ser inserida. Note que o código com a sequência de IF sequer prevê a possibilidade de uma exceção. Se ao menos houvesse um IF para tratar tudo que fosse diferente dos estados conhecidos, a situação ficaria um pouco melhor. Para tratar alguma ocorrência diferente de uma lista, utilizamos o E. Uma variável só pode ter um valor em um determinado instante. Assim, se a variável unidade-federativa estiver com o valor “Amapá” em um determinado momento, ela não poderá estar com o valor “Amazonas” naquele mesmo momento. Então, pela lógica, a variável estará com valor “Amazonas” ou “Amapá”. Entretanto, ao perguntarmos se a variável não está com um determinado valor, ou seja, pela negativa, estamos perguntando se a variável é diferente de um valor, ou se é diferente de vários valores. Assim, ao perguntarmos se a variável lida é diferente de uma série de valores, precisamos utilizar o E. A variável lida deve ser diferente de “Amapá” E (preste atenção a este E), ao mesmo tempo, essa mesma variável deve ser diferente de “Amazonas”. E deve ser diferente de cada uma das unidades federativas da tabela. Se essa variável for diferente de todas as outras, o sistema deve realizar alguma ação que aponte que exista algo inesperado nos dados de entrada. Então, um IF que prevê uma exceção ficaria com tantas condições associadas com E e tornaria mais trabalhosa a edição do programa. Contudo, como vimos, existem algumas alternativas. Primeiro, muitas linguagens permitem o uso de IF THEN ELSE. Note que a diferença está na estrutura e o resultado influenciará o tempo de execução. Compare as duas estruturas a seguir e responda às questões que são colocadas no final da segunda estrutura.
80 Laureate- International Universities
Estrutura 1:
Se estado = “Acre” então sigla = “AC”; fim do Se
Se estado = “Amazonas” então sigla = “AM”; fim do Se
Se estado = “Amapá” então sigla = “AP”; fim do Se Estrutura 2
Se estado = “Acre”
então sigla = “AC”;
Senão
Se estado = “Amazonas”
então sigla = “AM”;
Senão Se estado = “Amapá” então sigla = “AP”; Senão sigla= ”**”
Fim do se
Fim do se
Fim do se Figuras 3 e 4 – Recuperação da sigla do estado, sem e com o uso do “senão” na estrutura condicional. Fonte: Chamovitz (2015).
81
Lógica de programação
Responda mentalmente às seguintes perguntas: Ao ler uma variável com valor “Amapá”... 1. Quantas comparações foram feitas na estrutura 1? 2. Quantas comparações foram feitas na estrutura 2? 3. Se a variável lida for “Acre” ou se for “Amapá”, a estrutura 1 levará o mesmo tempo para processar cada uma? 4. Se a variável lida for “Acre” ou se for “Amapá”, a estrutura 2 levará o mesmo tempo para processar cada uma? Se você comparou as duas estruturas, deve ter percebido que a estrutura 2 é mais otimizada, porque as alternativas para comparação são exclusivas, ou seja, uma vez que o sistema descobriu que a variável lida é “Acre”, não precisa comparar com as outras alternativas, economizando tempo e recursos. Analise o seguinte fluxograma, que apresenta o fluxo de criação de um programa executável na linguagem C.
82 Laureate- International Universities
Abre o sistema pgm.c Programa código
Digita/edita o programa
Edita programa
Compilador C
Compila programa
Erro(s) de Sintaxe?
Sim
Não
pgm.obj
Liga com bibliotecas (sist)
Linker (linkeditor)
pgm.exe Entrada de Dados
Executa o código objeto
Sim
Erros de lógica ou de entrada de dados
Sim
Não Saída Correta
Termine / Pare
Figura 5 – Fluxo do processo de compilação. Fonte: Elaborada pelo autor, 2015.
83
Lógica de programação
O fluxo segue os passos a seguir.
• Primeiro, o programador abre o sistema que permitirá editar o programa. • Em seguida, abre o programa código e edita. • Pode continuar editando o programa... • Ao terminar a edição, o programador utiliza um compilador para compilar o programa. • Como já vimos, o compilador vai testar se existem erros. • Se existirem erros de sintaxe (esquecer-se de terminar comandos com ponto ou ponto e vírgula, por exemplo), o compilador não vai gerar o código-objeto.
• Nesse caso, o programador precisa editar o programa, corrigir o erro (como, por exemplo,
colocar o ponto no final do comando) e submeter o programa fonte para ser novamente compilado.
• Se não existirem erros de sintaxe, o programa-objeto será gerado. • A partir de um linker (ou linkeditor), o programa é agregado com bibliotecas. • É gerado um programa executável. • O programa executável vai processar os dados de entrada. • Caso ocorram erros por conta de entrada de dados, deve-se alterar ou corrigir a entrada de dados e reexecutar o programa.
• Caso ocorram erros por conta de lógica, deve-se editar e alterar o programa, seguindo novamente o fluxo.
• Sem
erros de sintaxe, lógica ou de entrada de dados, o programa gera a saída com sucesso e pode terminar ou parar.
Olhando o fluxograma, é fácil perceber que existem dois pontos de decisão, por conta da representação visual com losangos. O segundo ponto, na verdade, acabou absorvendo duas decisões e demonstra a possibilidade de se corrigir os dois problemas ao mesmo tempo. A decisão depende duas condições: 1. se existem erros de lógica; 2. se existem erros nos dados. E para o resultado ser o esperado (o programa estar funcionando corretamente), é necessário que as duas sejam satisfeitas: a condição (1) E a condição (2). Veja, a seguir, uma nova proposta, que coloca mais um ponto de decisão. O fluxograma é mais transparente, fácil de entender, pois demonstra que, na verdade, são 3 pontos de decisão.
84 Laureate- International Universities
Abre o sistema pgm.c Programa código
Digita/edita o programa
Edita programa
Compilador C
Compila programa
Erro(s) de Sintaxe?
Sim
Não
pgm.obj
Liga com bibliotecas (sist)
Linker (linkeditor)
pgm.exe Entrada de Dados
Executa o código objeto
Erros de lógica
Sim
Não Sim
Erros de entrada de dados
Não Saída Correta
Termine / Pare
Figura 6 – Fluxo do processo de compilação com 3 pontos de decisão. Fonte: Elaborada pelo autor, 2015.
85
Lógica de programação
Os pontos de decisão obedecem a princípios da lógica clássica. Em outras palavras, se o compilador encontrou erros de sintaxe, não há como gerar o programa executável. Analise agora as duas sentenças, pois ambas são verdadeiras e estão associadas aos mesmos princípios. 1. Se programa executável estiver com problemas de lógica ou se os dados não estiverem funcionando, sem problemas, o programa não estará correto. 2. O programa estará correto se ambas as condições – os problemas de lógicas e problemas com dados – estiverem funcionando, ou seja, sem problemas.
NÓS QUEREMOS SABER! O que é o princípio da não contradição? A lógica matemática adota como regras do pensamento os dois princípios: princípio da não contradição (toda proposição não pode ser verdadeira e falsa ao mesmo tempo) e princípio do terceiro excluído (toda proposição ou é verdadeira ou é falsa, verifica-se sempre um desses casos, nunca um terceiro). Aprenda sobre esses princípios com exemplos, na apostila: Iniciação à Lógica Clássica, disponível no link: <http://api.adm.br/ufrj/logica/tutorial.htm>.
Além do se/então/senão, algumas linguagens oferecem a seleção múltipla, pela qual um número é atribuído a uma variável dependendo da comparação que é realizada entre alternativas. No exemplo, X será comparado com V1. Escolha X
Caso 1:
Caso 2:
(bloco de código)
Caso 5…8:
(bloco de código)
Caso 3, 4:
(bloco de código)
(bloco de código)
Caso contrário:
(bloco de código)
Fim Escolha
Note que X é a variável que será comparada com valores numéricos. A sintaxe pode variar ou ter algumas limitações, dependendo da linguagem. No primeiro e no segundo casos, o código é executado se o valor lido for 1 ou 2. No terceiro caso, são considerados valores 3 e 4 como condição; na quarta opção, a comparação é feita com uma faixa de valores. No último caso, é executado um bloco de código caso nenhuma das alternativas seja igual à variável inicial x. 86 Laureate- International Universities
4.2 Estruturas de repetição Durante esta disciplina, entendemos a importância dos algoritmos e da lógica para que os sistemas funcionem. Podemos perceber que várias situações obedecem um fluxo e, durante o fluxo, existem estruturas de controle. Basicamente, podemos trabalhar com três elementos: atribuição, condição e repetição. Neste tópico, veremos a estrutura de repetição. Por exemplo, uma máquina de café para autoatendimento, dessas que encontramos em alguns estabelecimentos comerciais. Algumas exigem que você coloque o copo sob a torneira, outras já posicionam o copo e servem. Esse ato, servir o café, é um procedimento pelo qual um sensor enche o copo com cada elemento: café, água e leite. Existe um dispositivo de controle. O líquido vai enchendo o copo e, por alguma regra, ele cessa, para. Note, então, que existe uma repetição e uma condição nesse processo. Como dissemos, as estruturas de controle e fluxo são basicamente atribuição, repetição e comparação. A comparação serve para determinar se o fluxo continua ou não e geralmente é feita depois de uma possível atribuição. Vamos apresentar, a seguir, um fluxo de repetição. Você pode encontrar algumas variações, mas certamente seguirá vários princípios fundamentados nas explicações que seguem na Figura 7. Observe o fluxograma com atenção. Esse fluxo pode ser, por exemplo, a continuação de uma sequência de comandos anteriores e pode, também, estar sendo executado antes de outras tantas tarefas.
Estrutura de controle para repetição Comandos anteriores
A B
FALSO
VERDADEIRO
D C Próximos Comandos
Figura 7 – Fluxograma de repetição. Fonte: Elaborada pelo autor, 2015.
87
Lógica de programação
Repare que existem quatro pontos principais, representados pelas letras A, B, C e D. Um laço (em inglês loop) em programação é estabelecido a partir da continuidade de um valor considerado verdadeiro. Enquanto esse valor continuar verdadeiro, uma sequência de tarefas será executada. Em geral, uma das ações dessa sequência de tarefas vai modificar o estado de uma variável, que será testada como condição para continuidade do loop. Essa variável será declarada e inicializada antes do loop e com um valor que satisfaz a condição, de forma a permitir que o loop se inicialize. Um exemplo: a empresa Engeavant está em constante evolução. Um cadastro de produtos está sendo criado para registrar produtos resultantes do departamento de inovação da empresa. Imagine que a ficha dos produtos contém dois campos, “código” e “descrição”. São apenas uns vinte ou trinta registros e, no momento, o departamento de inovação e desenvolvimento de produtos criou as fichas para cada produto, armazenando temporariamente em uma caixa simples, enquanto a equipe de TI organiza, implementa e integra o novo sistema de produtos com os demais sistemas da empresa. Se você precisasse programar um computador para buscar tais fichas, utilizaria um algoritmo que seguiria o fluxo da Figura 7, considerando os momentos A, B, C e D. No momento A, podemos criar uma constante, que receberá um valor lido ou atribuído por você, o código do produto que procura. Vamos chamar essa constante de “procurado” e atribuir, por exemplo, o código do produto que procuramos, “034”. Você deve, também, criar e inicializar uma variável lógica que vai servir para controlar a continuidade da repetição. Podemos escolher um nome bem adequado, como, por exemplo, “achei”. A variável “achei” receberá o valor “F” (falso ou false), para que o teste de condição de loop do momento B aceite que o fluxo “entre no loop”. Nesse mesmo momento, deve-se abrir a caixa e colocar o seu índice (por exemplo, apontar o indicador) na primeira ficha (muitas linguagens oferecem comandos do tipo “posicione no primeiro registro” e também outro comando, “passe para o próximo registro”). Então, supondo-se que foi estabelecida a conexão e o arquivo foi aberto para leitura anteriormente, o momento A tem dois comandos:
• procurado= “034”; • achei:= “F”; • Posicione no primeiro registro; O momento B é aquele que testa uma ou mais condições para identificar se o fluxo segue adiante e inicia o loop ou, se a condição não for satisfeita, não deixa o fluxo seguir para iniciar o loop, passando imediatamente para o comando que vem após a finalização do loop (ou seja, após o momento C). Se a condição for composta, deverá obedecer a regras da lógica e, se for necessário, deve-se utilizar parênteses para estabelecer prioridades (isso pode ocorrer com três ou mais condições combinadas). A condição, em nosso exemplo, deverá estar relacionada com duas situações: a variável de controle “achei” deve ser falsa E, ao mesmo tempo, o registro atual não é inexistente (ou seja, após ler o última ficha, se você tentar acessar a próxima, percebe que não existe mais nenhuma). A condição para o controle (ou o comando) “Enquanto” é uma condição composta e fica com duas expressões, assim: Enquanto (expressão 1) e (expressão 2). Veja:
• Enquanto achei= “F”
e não-cheguei-ao –final- do –arquivo faça
O momento D executa comandos e ações dentro do loop, ou seja para aquela situação específica, relacionada com a variável de controle. Em nosso exemplo, estamos procurando um determinado código, “034” e este código já está armazenado em uma constante que tem o nome de “procurado”. 88 Laureate- International Universities
No momento D, devemos comparar se o valor que procuramos é igual ao valor do código, representado pelo campo “código” na ficha. O resultado dessa comparação poderá ser verdadeiro ou falso. Se for verdadeiro, devemos ler a descrição e enviar para algum local: no nosso exemplo não automatizado, podemos dizer em voz alta ou anotar em um papel. Então o momento D ficaria assim:
• Se procurado = fichadeproduto.código Então
Diga em voz alta a descrição
Achei = .V.
Senão
(Não faça nada)
Fim do se
O momento C ocorre ainda dentro do loop e só vai acontecer se você não encontrou o código. O momento C é aquele que passa para a próxima ficha. Lembre-se de que após o momento C vem o momento B, que vai testar as duas condições que devem ser verdadeiras: “Achei” deve ser F e não se chegou ao final das fichas. Então, o momento C ficaria com o seguinte comando:
• Passe para a próxima ficha (desloque seu dedo indicador, por exemplo) • Retorne ao momento B (para testar as duas condições que devem ser verdadeiras para entrar no loop).
No momento B, haverá o teste para “achei” e para “fim-de-arquivo”. Se “achei” continuar falso e ainda houver fichas, o sistema entra no loop. Se “achei” for verdadeiro é porque a ficha já foi encontrada e, nesse caso, uma das condições foi quebrada. Logo, o sistema não entrará no loop e seguirá para depois do momento C. Se “achei” for falso e a leitura da nova ficha (feita no momento C) resultar em final de arquivo, quer dizer que uma das duas condições foi quebrada e o sistema não entrará no loop, seguindo, também, para depois do momento C. O exemplo anterior foi importante para mostrar os quatro momentos existentes em fluxos de repetição. Foram apresentados um fluxograma e os principais comandos, em pseudocódigo, para mostrar como funciona a lógica do fluxo de repetição. Agora, podemos acessar um programa e relacionar o conhecimento adquirido até o momento com um programa real. Esse exemplo mostra de forma bem detalhada como ocorre o controle do loop em uma situação que envolve um cadastro de pessoas em uma situação usual: indicação para treinamento a partir de dados de avaliação. Uma empresa de engenharia realiza avaliação de desempenho duas vezes por ano. A cada avaliação, chefes e colegas avaliam o desempenho de seus pares e chefias, utilizando diversos critérios. Ao final, seguindo uma tabela estabelecida pelo departamento de desenvolvimento de pessoas, fica registrada para cada funcionário uma nota que representa o resultado de sua avaliação. Após o término do período da avaliação e registro dos resultados, o engenheiro-chefe precisa identificar colaboradores que precisam de treinamento. Para isso, consultará uma base de dados dispostos em uma tabela e realizará as atividades que veremos a seguir, acessando linha a linha o registro de cada funcionário, enquanto a condição de “final de lista” não for atingida. O engenheiro copia para a nova tabela todas as linhas com nota abaixo de 7. A seguir, veja a tabela principal e a tabela com notas abaixo de 7. 89
Lógica de programação
Lista de funcionários/funcionárias
Matrícula
Nome
Avaliação
034
Alberto Fontance
9,0
035
Berenice Maetine
6,0
...
...
...
043
Zacarias Fontti
7,0
Tabela 1 – Lista de funcionários/funcionárias. Fonte: Chamovitz, 2015.
Lista de funcionários/funcionárias para treinamento
Matrícula
Nome
Avaliação
035
Berenice Maetine
6,0
Tabela 2 – Lista de funcionários/funcionárias para treinamento. Fonte: Chamovitz, 2015.
Veja passo a passo as ações do engenheiro e tente perceber se faltou algum passo. 1. Checar a condição de final de lista de funcionários, se não houver mais linhas com nota, o engenheiro encerra as atividades. Mas, se a linha estiver com nome e nota, o engenheiro compara a nota de avaliação com o padrão estabelecido, por exemplo, “7”. 2. Se a nota for maior ou igual a 7, o engenheiro salta para a próxima linha, pois o registro não interessa. 3. Caso a nota seja menor que 7, o engenheiro vai copiar a matrícula, nome do colaborador e nota para uma lista de treinamento. Em seguida, salta para a próxima linha da lista de funcionários/funcionárias. 4. O trabalho reinicia no item 1. Como você já sabe, algoritmos podem estar mais ou menos detalhados. Além disso, na grande maioria das vezes, existem várias soluções para um único problema. Se você encontrou alguma solução diferente, pode testar em um programa ou, se ainda não programou, pode discutir com alguns colegas.
Linguagem de programação Agora vamos apresentar alguns exemplos em uma linguagem, nesse caso, o C++. Note que alguns ambientes ou linguagens podem não permitir uso de acentuação. Note também que existem comandos que não foram apresentados aqui, mas estão comentados ao lado. O que está depois de “//” não é interpretado pelo compilador e fica como comentário. Sugere-se sempre incluir comentários que facilitem a compreensão do código por outra pessoa ou após um longo período, quando o programador já pode ter esquecido sobre as condições nas quais escreveu o código.
90 Laureate- International Universities
#include <stdio.h> tput)
//inclui a biblioteca padrão (std) de entrada e saida (io, input-ou-
int main () {
int num;
printf (“Digite o valor padrão de avaliação e tecle enter: “);
scanf (“%d”,&num);
if (num==7) {
printf (“\n\nEsta resposta esta certa!\n”);
printf (“\n\n O valor padrao e’ 7”);
} else { printf (“\n\nVoce errou!\n”); printf (“O valor minimo deve ser igual a 7”); } printf (“\n\n Digite um numero e enter para sair: “);
scanf (“%d”,&num);
return(0);
Esse código é executado apenas uma vez. O sistema pede para que o usuário digite um número. Em seguida, o código utiliza a condição para:
• executar
um bloco de instruções (note que o bloco é delimitado por chaves) se for verdadeira OU
• executar outro bloco de instruções se a condição for falsa.
91
Lógica de programação
Podemos estender a estrutura if-else para if-else if e, no final, ficam as instruções que serão executadas caso nenhuma das anteriores seja satisfeita. Assim: if (condição_1) declaração_1; else if (condição_2) declaração_2; else if (condição_3) declaração_3; else if (condição_n) declaração_n; else declaração_default;
Repetição – o comando for O comando for é uma alternativa ao comando do while e permite que blocos de instruções sejam executados indefinidamente, ou até que uma ou mais condições sejam atingidas. Algumas linguagens permitem algumas variações para executar repetições, como o comando while, “do” e assemelhados. O loop “for” programa a repetição de um comando ou de um bloco de comandos. Veremos um exemplo em C++ que apresenta os primeiros 50 números inteiros na tela: #include <stdio.h> int main () {
int count;
for (count=1; count<=50; count++) printf (“%d “,count);
printf (“\n\n Digite um numero e tecle enter para terminar: “);
scanf (“%d”,&count); return(0);
}
Lembre-se de que a biblioteca stdio (standard input output) contém código para lidar com entrada e saída e vai ser incorporada ao programa durante a compilação. Note que, no exemplo anterior, o incremento da variável count é feito usando o operador de incremento, count++, que equivale a count = count +1, ou seja, adicione 1 para a variável count. Em C++, o comando do-while tem a seguinte estrutura: do { declaração; } while (condição);
92 Laureate- International Universities
Em algumas linguagens, chaves limitam blocos de comandos. Mesmo que a declaração seja apenas um comando, é uma boa prática deixar as chaves. Note que, em C++, o ponto e vírgula final é obrigatório. Algumas linguagens não limitam comandos com ponto e vírgula. Veja, a seguir, um exemplo com escolha de nomes para formar uma equipe de trabalho: #include <stdio.h> int main () {
int i;
do { printf (“\n\nEscolha o melhor integrante de sua equipe pelo numero:\n\n”); printf (“\t(1)...Marcelo\n”); printf (“\t(2)...Arnaldo\n”); printf (“\t(3)...Luiz\n\n”); scanf(“%d”, &i); } while ((i<1)||(i>3));
switch (i)
{ case 1:
printf (“\t\tVoce escolheu Marcelo.\n”);
break; case 2:
printf (“\t\tVoce escolheu Arnaldo.\n”);
break; case 3:
printf (“\t\tVoce escolheu Luiz.\n”);
break; } printf (“\n\n Digite um numero e tecle enter para terminar: “);
scanf (“%d”,&i);
return(0); }
93
Lógica de programação
Esse bloco foi programado para ser executado enquanto a variável “i” estiver entre 1 e 3. Ao digitar o número, o programa entra em um bloco case, que executa comandos de acordo com uma condição. Se for 1, vai listar o primeiro nome e parar, porque vai executar o comando break. Se for 2, apresentará o nome do segundo e vai parar também. E se for 3, agirá da mesma forma, só que com o terceiro membro.
4.3 Solução de problemas Segundo o dicionário Michaelis, um problema pode ser definido (primeira definição) como uma questão levantada para inquirição, consideração, discussão, decisão ou solução. Um problema envolve dificuldade. Um dos motivos para essa dificuldade é a ausência de informação. Geralmente, a solução de um problema envolve três etapas: estruturação, avaliação e síntese (Gomes, 2007). Chamovitz (2007, p. 7) apresenta perguntas que ajudam na estruturação de problemas: 1. O problema é o verdadeiro problema? 2. Já houve reflexão racional (não-emocional) para conhecer o problema? 3. Todas as informações relevantes foram recuperadas? 4. Já foi identificado o núcleo da questão? 5. Comprometimentos de natureza moral e ética foram considerados? 6. Já existe um conjunto amplo de alternativas viáveis? 7. Objetivos quantitativos e qualitativos da decisão já estão em uma lista? 8. Conjuntos de critérios de decisão estão presentes para cada objetivo? 9. Consequências e probabilidades de ocorrência para cada alternativa, seguindo cada critério estão relacionadas? 10. Existe algum método analítico que utiliza abordagem multicritério?
Tipos de problemas Segundo a decisão multicritério discreta (DMD) apresentada por Chamovitz (2007), a decisão pode envolver quatro tipos de solução: • Problemas Alfa são aqueles em que a decisão implica em se escolher a melhor alternativa ou as melhores alternativas; • Problemas Beta são aqueles em que a decisão implica em se aceitar as alternativas que parecem boas e descartar as que parecem ruins, ou seja, classificar as alternativas; • Problemas Gama são aqueles em que se pretende gerar uma ordenação das alternativas • Problemas Delta são aqueles em que a decisão implica em se realizar uma descrição das alternativas. (CHAMOVITZ, 2007, p. 7).
Note que problemas alfa exigem o conhecimento dos critérios. Se os critérios forem mal compreendidos ou os cálculos estiverem errados, a melhor alternativa poderá não ser identificada. Da mesma forma acontece com cada um dos outros três problemas: os critérios e os cálculos devem estar bem claros para que se obtenham os resultados desejados. Problemas de lógica implicam conhecer e estudar a lógica. A partir da construção de estruturas e da utilização de modelos já existentes e consagrados, pode-se ganhar tempo. Assim, é importante conhecer bem o problema e as soluções já implementadas. Confira alguns exemplos na sequência. Um sistema de contas a pagar envolve valores a serem pagos, datas, fornecedores e tipos de serviço ou produto. Repare que um sistema de contas a receber envolve valores a serem recebidos, datas, clientes e tipos de serviço e produto. Os dois sistemas funcionam de forma bem se94 Laureate- International Universities
melhante. Até certo ponto, dados de fornecedores e dados de clientes são bem parecidos. Cada um terá código, nome, endereço, etc. Então, podemos concluir que algumas rotinas poderão ser compartilhadas nesse tipo de sistema. Castilho, Silva e Weingaertner (2015) desenvolveram algumas ideias sobre problemas e soluções. Em primeiro lugar, destacam que um problema não tem, em geral, uma solução única. Em segundo, algumas soluções podem ser mais eficazes que outras, se for utilizado um determinado critério ou conjunto de critérios. Em terceiro, alguns problemas podem ser casos particulares de problemas genéricos. Assim, os autores sugerem resolver problemas mais genéricos e os casos particulares desse problema genérico estarão consequentemente resolvidos também. Os autores apresentam, ainda, sete formas de se resolver um problema que envolve contagem de pessoas em um evento. Problemas simples podem ser resolvidos com sistemas simples. Existe, porém, uma categoria de problema que é classificada como problemas complexos, que podem envolver sistemas complexos. Mas o que são sistemas complexos? Pontarolo et al. (2005) apresentam um ambiente para programar e modelar sistemas complexos associados a multiagentes. “Sistemas complexos são difíceis de entender porque as causas e os efeitos não estão relacionados de forma direta, ou seja, existem correlações entre eventos distantes no tempo e no espaço.” (PONTAROLO et al., 2005, p. 2). A ideia aqui é mostrar como a lógica de programação pode ser utilizada para o estudo de problemas complexos, mais especificamente os sistemas complexos formados por multiagentes. A modelagem baseada em agentes, em inglês agent based modelling, permite a simulação a partir da existência de vários agentes interagindo uns com os outros. Assim, agentes individuais podem ser pessoas, carros, bactérias, insetos, nações, organizações. Esses agentes interagem entre si e também com seu ambiente. A simulação visa a descobrir características e situações emergentes, de forma a se entender melhor a dinâmica do processo.
NÓS QUEREMOS SABER! Existe algum ambiente interessante e fácil de usar para lidar com modelagem baseada em agentes? O Netlogo pode ser uma boa opção para lidar com modelagem baseada em agentes.
Azevedo et al. (2005) apresentam o NetLogo, informando que foi desenvolvido por Uri Wilensky em 1999 e que é atualizado pelo Center for Connected Learning and Computer-Based Modeling, da Northwestern University, Evanston, Illinois. Os autores complementam informando que o NetLogo é um ambiente de modelagem programável para explorar comportamento de sistemas descentralizados e, também, sistemas complexos. Este ambiente é particularmente bem indicado para a modelagem de sistemas complexos desenvolvidos no decorrer do tempo. Assim, segundo o criador do ambiente, o NetLogo oferece simplicidade para se aprender a modelagem baseada em agentes mesmo para quem não tem habilidade em programação e ao mesmo permite a utilização da linguagem de forma bem avançada, por programadores experientes. Um ambiente interessante e relativamente simples para se explorar é o ambiente NetLogo, que é composto de três tipos de agentes: turtles, patches e observer. Cada um dos agentes tem características e comportamentos (lembrando o paradigma de orientação a objetos). NetLogo usa 95
Lógica de programação
uma linguagem de modelagem própria, derivada da linguagem de programação Logo do Media Lab – MIT. O Netlogo é uma ferramenta de acesso e uso gratuito. Turtles são representações individuais que podem ter comportamentos (são procedures). Por exemplo, um agente do tipo turtle pode andar para frente. Se esse comportamento estiver dentro de um laço (loop), ele continuará avançando. E se houver um controle, um sensor que pergunta se existe algum outro agente no caminho, ele poderá executar outro comportamento (outra procedure). Patches representam uma área de um tabuleiro com dimensões definidas pelo programador. Os agentes turtle se deslocam sobre o tabuleiro que é subdividido em células (quadrados), os patches. O observer representa o observador que pode digitar comandos ou entrar com dados. Por exemplo, o comportamento “avance” pode fazer o agente andar 10 “passos”. É muito simples: to proc_avance forward 10 end
Geralmente, os agentes turtle são criados por comandos específicos. Uma vez criados, podem adquirir formas e serem posicionados no tabuleiro. A partir daí, eles podem checar a vizinhança (se existem outros agentes perto) antes de avançarem. O programador pode mudar estados dos agentes que se encontraram, como, por exemplo, a cor mudar de verde para vermelho, indicando que houve uma contaminação, em um modelo sobre epidemias. O Netlogo oferece uma vasta biblioteca com exemplos para a solução de problemas mais simples e também complexos. Os exemplos permitem um aprendizado passo a passo.
NÃO DEIXE DE LER... O livro Lógica de Programação: a construção de algoritmos e estruturas de dados, de A. L. V. Forbellone e H. F. Eberspächer, que apresenta de forma bem didática os algoritmos e os recursos de lógica aprendidos neste capítulo.
96 Laureate- International Universities
NÃO DEIXE DE VER... Websites oficiais sobre Netlogo e tutoriais.
• Netlogo Manual: <http://ccl.northwestern.edu/netlogo/docs/> • Netlogo Modeling Commons: <http://modelingcommons.org/> • Netlogo Models Library: <http://ccl.northwestern.edu/netlogo/models/> • Netlogo
Community Models: <http://ccl.northwestern.edu/netlogo/models/ community/index.cgi>
• Tutorial
Netlogo: NetLogo.htm>
<http://www.inf.ufes.br/~liviaufmt/Disciplina/tutorial_
• Tutorial PRISMA: Tutorial de NetLogo: <http://cftc.cii.fc.ul.pt/PRISMA/capitulos/ netlogo/>
VOCÊ O CONHECE? Edsger Wybe Dijkstra (1930 – 2002) foi um cientista da computação holandês conhecido por suas contribuições nas áreas de desenvolvimento de algoritmos e programas, de linguagens de programação (pelo qual recebeu o Prêmio Turing de 1972 por suas contribuições fundamentais), sistemas operacionais e processamento distribuído. Entre suas contribuições para a ciência da computação, está incluído o algoritmo para o problema do caminho mínimo (também conhecido como algoritmo de Dijkstra), o sistema operacional THE e a construção de semáforos para coordenar múltiplos processadores e programas.
97
Síntese Síntese
Neste capítulo, estudamos com mais profundidade as estruturas condicionais e as estruturas de repetição. Alguns pontos podemos ser destacados:
• É importante entender a lógica e utilizar as estruturas adequadamente. Afinal, um programa
que funciona é bom, mas o ideal é que ele utilize menos recursos e que, durante o seu funcionamento, exponha minimamente os dados e as informações a riscos.
• Estudos de caso podem ilustrar o uso adequado da lógica de programação. • O fluxograma é um instrumento que pode ser utilizado para entender melhor a lógica de programação.
• Existem
ambientes específicos, como o Netlogo, que são indicados para lidar com a lógica em sistemas complexos baseados em multiagentes. Referências e tutoriais também podem ajudar a entender esses sistemas.
• Independentemente da linguagem escolhida, a lógica de programação dependerá do uso adequado de atribuições, condições e repetições.
98 Laureate- International Universities
Referências
Bibliográficas
AZEVEDO, L. L. Tutorial: Exploração do ambiente orientado a agente NetLogo. In: XVI SIMPÓSIO BRASILEIRO DE INFORMÁTICA NA EDUCAÇÃO, 2005, Juiz de Fora. Anais do XVI Simpósio Brasileiro de Informática na Educação. Vitória: Universidade Federal do Espírito Santo, 2005. Disponível em: <http://www.inf.ufes.br/~liviaufmt/Disciplina/tutorial_NetLogo.htm>. Acesso em: mar. 2015. AZEVEDO, L. L. et al. Ambientes computacionais orientados a agentes para apoio à aprendizagem baseada em simulação. In: XVI SIMPÓSIO BRASILEIRO DE INFORMÁTICA NA EDUCAÇÃO, 2005, Juiz de Fora. Anais do XVI Simpósio Brasileiro de Informática na Educação. Vitória: Universidade Federal do Espírito Santo, 2005. Disponível em: <http://www.inf.ufes. br/~liviaufmt/Arquivo-pdf/ambientes%20computacionais%20orientados%20a%20agentes%20 para%20apoio%20a%20aprendizagem%20baseado%20em%20simulacao.pdf>. Acesso em: mar. 2015. AZEVEDO, L. L.; PANTAROLO, E.; MENEZES C. S. Tutorial: Exploração do ambiente NetLogo. In: XVI SIMPÓSIO BRASILEIRO DE INFORMÁTICA NA EDUCAÇÃO, 2005, Juiz de Fora. 2005, Juiz de Fora. Anais do XVI Simpósio Brasileiro de Informática na Educação. Vitória: Universidade Federal do Espírito Santo, 2005. Disponível em: <http://www.inf.ufes.br/~liviaufmt/versao%20 final%20mini-curso/Tutorial_Mini-curso.pdf>. Acesso em: jan. 2012. CASTILHO, M.; SILVA F.; WEINGAERTNER, D. Algoritmos e Estruturas de Dados I: nota de aula. Versão 0.7.1. Curitiba: Universidade Federal do Paraná, Departamento de Informática, 2015. Disponível em: <http://www.inf.ufpr.br/cursos/ci055/apostila.pdf>. Acesso em: mar. 2015. CHAMOVITZ, I. Avaliação de intangíveis em organizações sem fins lucrativos utilizando fundamentos de apoio multicritério à decisão. In: PROFUNDÃO 2007 – XI ENCONTRO DE ENGENHARIA DE PRODUÇÃO DA UFRJ. 2007, Rio de Janeiro. Anais do XI Encontro de Engenharia de Produção da UFRJ. Rio de Janeiro: Universidade Federal do Rio de Janeiro, 2007. Disponível em <http://api.adm.br/artigos/wp-content/uploads/2007/05/intangiveis_profundao2007_2. pdf>. Acesso em: 13 jul. 2015. FORBELLONE, A. L. V.; EBERSPÄCHER, H. F. Lógica de programação. São Paulo: Pearson Prentice Hall, 2005. GASPARIN, G. Em plebiscito, eleitores do Pará rejeitam divisão do estado. G1, Belém, 11 dez. 2011. Atualizado em 12 dez. 2011. Disponível em: <http://g1.globo.com/politica/noticia/2011/12/em-plebiscito-eleitores-do-para-rejeitam-divisao-do-estado.html>. Acesso em: 5 abr. 2015. GOMES L.F.A.M. Teoria da Decisão. São Paulo: Editora Thompson, 2007. 116p. (Coleção Debates em Administração). Bibliografia: p. 1-20. ISBN 85-221-0529-4. PONTAROLO, E. et al. Exploração do ambiente orientado a agente NetLogo. In: XVI SIMPÓSIO BRASILEIRO DE INFORMÁTICA NA EDUCAÇÃO, 2005, Juiz de Fora. Anais do XVI Simpósio Brasileiro de Informática na Educação. Vitória: Universidade Federal do Espírito Santo, 2005. Disponível em: <http://www.inf.ufes.br/~liviaufmt/Arquivo-pdf/MiniCursoNetLogo.pdf>. Acesso em: 6 abr. 2015. PROBLEMA. In: DICIONÁRIO de Português Online Michaelis. Disponível em: <http://michaelis. uol.com.br/moderno/portugues/index.php?lingua=portugues-portugues&palavra=problema>. Acesso em: 13 jul. 2015. 99
Minicurrículo do autor Ilan Chamovitz é graduado em Administração (UFRJ) e pós-graduado em Análise de Sistemas
(PUC). Possui MBA em Tecnologias da Informação em Comunicações (FGV), é mestre em Informática (UFRJ) e Doutor em Engenharia da Produção (UFRJ). Pesquisador associado ao grupo LAB Fuzzy (COPPE/UFRJ), também colabora em pesquisas de pós-doutorado na Manchester Business School, na universidade de Manchester, na Inglaterra.
101