Algoritmos e lógica da programação Ricardo Sobjak Introdução à lógica da programação Sumário 1 Introdução à lógica da programação .................................................................................6 Lógica ..............................................................................................................................................6 Sequencia Lógica .........................................................................................................................6 Instruções .......................................................................................................................................7 Algoritmos ......................................................................................................................................7 Programas ......................................................................................................................................9 2 Representação de algoritmos ............................................................................................ 11 Representação em linguagem narrativa ............................................................................. 11 Representação com fluxograma convencional ................................................................. 15 Representação em Pseudocódigo ....................................................................................... 17 Comentários ........................................................................................................................... 18 Fases de um algoritmo ............................................................................................................ 19 Exemplo das fases no Algoritmo...................................................................................... 20 Teste de Mesa ............................................................................................................................ 21 3 Tipos de dados ....................................................................................................................... 23 Numéricos ................................................................................................................................... 23 Inteiro ....................................................................................................................................... 23 Real ........................................................................................................................................... 23 Alfanuméricos............................................................................................................................. 24 Caractere ................................................................................................................................. 24 Cadeia ...................................................................................................................................... 24 Lógicos ......................................................................................................................................... 24 4 Variáveis, Constantes e Expressões .................................................................................. 26 2 Introdução à lógica da programação Variáveis ....................................................................................................................................... 26 Constantes................................................................................................................................... 29 Expressões ................................................................................................................................... 30 5 Operações básicas ................................................................................................................ 31 Atribuição .................................................................................................................................... 31 Operadores Aritméticos .......................................................................................................... 32 Operadores Relacionais........................................................................................................... 32 Operadores Lógicos ................................................................................................................. 33 Operador de caractere ............................................................................................................ 36 Prioridade de Operadores ...................................................................................................... 37 6 Entrada e Saída de dados ................................................................................................... 40 Comando de entrada de dados ........................................................................................... 40 Comando de saída de dados ................................................................................................ 41 7 Processos de Seleção ........................................................................................................... 44 Estrutura SE-ENTÃO-SENÃO (IF-THEN-ELSE) .................................................................. 44 Estrutura SELECIONE-CASO (SWITCH-CASE)................................................................... 48 8 Processos de Repetição ....................................................................................................... 50 Estrutura de repetição ENQUANTO-FAÇA (WHILE-DO) ............................................... 50 Estrutura de repetição REPITA-ATÉ QUE (REPEAT UNTIL)............................................ 51 Estrutura de repetição PARA-FAÇA (FOR-TO-DO) ......................................................... 52 9 Modularização ........................................................................................................................ 53 Mecanismo de Funcionamento ............................................................................................. 54 Definição de Subalgoritmos ................................................................................................... 55 Procedimentos ........................................................................................................................... 56 Funções ........................................................................................................................................ 57 3 Introdução à lógica da programação 10 Tipos homogêneos de dados compostos ................................................................. 61 Variáveis indexadas unidimensionais – Vetores ............................................................... 61 Declaração de vetores......................................................................................................... 62 Leitura e escrita de dados nos vetores ........................................................................... 62 Utilização de Vetores Relacionados ..................................................................................... 64 Variáveis indexadas bidimensionais – Matrizes ................................................................ 68 Declaração e Utilização de Matrizes ............................................................................... 69 11 Tipos heterogêneos de dados compostos ................................................................ 71 Registros ...................................................................................................................................... 71 Atribuição .................................................................................................................................... 72 Leitura e escrita .......................................................................................................................... 73 Exemplo ....................................................................................................................................... 73 4 Introdução à lógica da programação Apresentação Prezado estudante, Saber construir algoritmos é um fator primordial para que se possam desenvolver programas em linguagens de computadores, isso depende do entendimento da estrutura lógica de funcionamento. Em cursos de níveis técnico e superior, que possuam relação com desenvolvimento de software, ou até mesmo, algumas engenharias, preveem unidades curriculares que tratam, em seus ementários, de conteúdos referentes à construção de algoritmos e desenvolvimento da lógica da programação. Este material foi elaborado com o objetivo apresentar a maioria desses conceitos, para que você possua utilizá-lo como ferramenta de apoio na compreensão e apropriação destes conhecimentos. Este material ainda está em fase de construção e formulação do seu conteúdo, portanto, em breve será disponibilizado uma versão mais elaborada. 5 Introdução à lógica da programação 1 Introdução à lógica da programação Lógica O conceito de lógica está relacionado com a ideia de ter um raciocínio estruturado, partindo-se do pressuposto que o pensamento deve ter uma linha coerente de estruturação. Dentro da programação, a lógica é um aspecto essencial para que seja possível encadear os pensamentos, de forma que estes sejam raciocinados com justeza e precisão, a fim de que se possam atingir objetivos previamente determinados. Todo o desenvolvimento de sistema necessita que o meio para se atingir um objetivo, seja organizado dentro de uma sequencia lógica de ações e decisões. A aprendizagem de lógica não se constitui como um fim, mas um meio de garantir que nosso pensamento se faz para atingir objetivos verdadeiros. Sequencia Lógica Uma “sequencia lógica” pode ser considerada como a organização sequencial de passos “lógicos” que são executados para atingir um determinado objetivo na solução de um problema. No contexto de programação, estes passos ou pensamentos podem ser descritos como uma sequencia de instruções que são escritas em linguagem computacional para ser interpretadas por um determinado compilador. Na Figura 1.1 é possível visualizar 6 Introdução à lógica da programação uma demonstração de sequencia lógica, onde se têm os passos que ocorrem na “alimentação” de uma planta carnívora. Figura 1.1 Demonstração da sequencia lógica de alimentação de uma planta carnívora. Instruções Na linguagem comum, entende-se por instruções “um conjunto de regras ou normas definidas para a realização ou emprego de algo”. Em informática, porém, instrução é a informação que indica a um computador uma ação elementar a executar. Convém ressaltar que uma ordem isolada não permite realizar o processo completo, para isso é necessário um conjunto de instruções colocadas em ordem sequencial lógica. Por exemplo, se quisermos fazer uma omelete, precisaremos colocar em prática uma série de instruções, que basicamente seria: quebrar os ovos, bater a clara e a gema, fritar a mistura, entre outros. É evidente que essas instruções têm que ser executadas em uma ordem adequada, pois não se pode fritar a mistura antes de quebrar os ovos. Dessa maneira, uma instrução tomada em separado não tem muito sentido. Para obtermos o resultado, precisamos colocar em prática o conjunto de todas as instruções, na ordem correta. Algoritmos Algoritmo é a descrição de um conjunto de comandos que, obedecidos, resultam numa sucessão finita de ações. Um algoritmo pode ser pensado como uma receita, que é formada por uma sequencia de instruções ordenadas de forma lógica para a resolução de uma determinada tarefa ou problema. Estas tarefas não podem ser redundantes nem subjetivas na sua definição, devem ser claras e precisas. 7 Introdução à lógica da programação Algoritmo não é a solução de um problema, pois se assim fosse cada problema teria um único algoritmo. Algoritmo é um caminho para a solução de um problema, e em geral, os caminhos que levam a uma solução são muitos. O aprendizado de algoritmos é adquirido através de muitos exercícios. Algoritmos só são aprendidos construindo-os e testando-os. Um algoritmo deve possuir as seguintes características: Ter início e fim; Ser escrito em termos de ações ou comandos bem definidos; Deve ser fácil de interpretar e codificar, ou seja, ele deve ser o intermediário entre a linguagem falada e a linguagem de programação; Ter uma sequencia lógica. Até mesmo as coisas mais simples, podem ser descritas em sequencias lógicas. A seguir temos dois exemplos de algoritmos. Algoritmo para “Chupar uma bala”: Pegar a bala; Retirar o papel; Chupar a bala; Jogar o papel no lixo. Algoritmo para “Somar dois números quaisquer”: Escreva o primeiro número no retângulo A; Escreva o segundo número no retângulo B; Some o número do retângulo A com número do retângulo B e coloque o resultado no retângulo C. Retângulo A Retângulo B + Resultado = 8 Introdução à lógica da programação Programas Os programas de computadores nada mais são do que algoritmos escritos numa linguagem de computador (Pascal, C, Cobol, Fortran, Visual Basic, Java, PHP, entre outras) e que são interpretados e executados por uma máquina, no caso um computador. Notem que dada esta interpretação rigorosa, um programa é por natureza muito específica e rígida em relação aos algoritmos da vida real. As Figura 1.2etapas e os elementos envolvidos na atividade de programação podem ser visualizados na Figura 1.2, nela é possível perceber que a etapa inicial da programação é a existência de um problema, que consequentemente necessita de uma solução. A partir do problema é necessário conhecer (ou procurar) a sua solução. Uma vez conhecendo a solução do programa é necessário adaptá-la ao mundo da máquina. Esta adaptação produz o algoritmo, o qual é independente de linguagem de programação e contém a essência do programa. Por fim, o passo que exige um maior esforço é codificação, em que o programador transcreve o algoritmo seguindo as regas de uma linguagem de programação, que por sua vez, depois de compilado irá gerar o programa executável. O algoritmo tem um papel fundamental por ser o elo entre os dois mundos. Percebe-se que a atividade de programação tem início com a construção do algoritmo. MUNDO REAL MUNDO COMPUTACIONAL Linguagem de Programação Problema Algoritmo Codificação Programa fonte Tradução Adaptação Solução Programa executável Figura 1.2 Elementos e etapas da atividade de programação 9 Introdução à lógica da programação Exercícios 1) Desenvolva a sequencia lógica para tomar um banho. 2) Descreva com detalhes a sequencia lógica para trocar o pneu de um carro. 3) Faça um algoritmo para trocar uma lâmpada, descrevendo todos os detalhes. 10 Representação de algoritmos 2 Representação de algoritmos Existem diversas formas de representação de algoritmos, algumas delas tratam os problemas apenas em nível lógico, abstraindo-se de detalhes de implementação muitas vezes relacionados com alguma linguagem de programação específica. Por outro lado existem formas de representação de algoritmos que possuem uma maior riqueza de detalhes e muitas vezes acabam por obscurecer as ideias principais do algoritmo, dificultando seu entendimento. Dentre as formas de representação de algoritmos mais conhecidas podemos citar: Descrição Narrativa; Fluxograma Convencional; Pseudocódigo, também conhecido como Linguagem Estruturada ou Portugol. Representação em linguagem narrativa Nesta forma de representação os algoritmos são expressos diretamente em linguagem natural. Esta representação é pouco usada na prática porque o uso da linguagem natural muitas vezes dá oportunidade a más interpretações, ambiguidades e imprecisões. Por exemplo, a instrução "afrouxar ligeiramente as porcas" no algoritmo da troca de pneus está sujeita a interpretações diferentes por pessoas distintas. Uma instrução mais precisa seria: "afrouxar a porca, girando-a 30º no sentido anti-horário". Descrevemos então uma atividade bem cotidiana: trocar uma lâmpada. Apesar de parecer simples, muitas vezes fazemos este tipo de atividade inconscientemente, sem percebermos os pequenos detalhes. Vejamos como seria descrevê-la passo a passo: Pegar uma escada; Posicionar a escada embaixo da lâmpada; Buscar uma lâmpada nova; Subir na escada; 11 Representação de algoritmos Retirar a lâmpada velha; Colocar a lâmpada nova. Para se trocar a lâmpada, é seguida uma determinada sequencia de ações, representadas através desse algoritmo. Como isso pode ser seguido por qualquer pessoa, estabelece-se aí um padrão de comportamento. A sequencialização tem por objetivo reger o fluxo de execução, determinando qual ação vem a seguir. O algoritmo anterior tem um objetivo bem específico: trocar uma lâmpada. E se a lâmpada não estiver queimada? O algoritmo faz com ela seja trocada do mesmo modo, não prevendo essa situação. Para solucionar este problema, podemos efetuar um teste seletivo, verificando se a lâmpada está ou não queimada: Pegar uma escada; Posicionar embaixo da lâmpada; Buscar uma lâmpada nova; Ligar o interruptor; Se a lâmpada não acender, então: o Subir na escada; o Retirar a lâmpada velha; o Colocar a lâmpada nova. Dessa forma, algumas ações estão ligadas à condição (lâmpada não acender). No caso da lâmpada acender, as três linhas, a seguir, não serão executadas: Subir na escada; Retirar a lâmpada velha; Colocar a lâmpada nova. Em algumas situações, embora o algoritmo resolva o problema proposto, a solução pode não ser a mais eficiente. Exemplo: três alunos devem resolver um determinado problema: O aluno A conseguiu resolver o problema executando 35 linhas de programa; O aluno B resolveu o problema executando 10 linhas de programa; O aluno C resolveu o problema executando 54 linhas de programa. 12 Representação de algoritmos Obviamente, o algoritmo desenvolvido pelo aluno B é menor e mais eficiente que os demais. Isso significa que há código desnecessário nos demais programas. Dessa forma, podemos aperfeiçoar o algoritmo anterior, uma vez que buscamos a escada e a lâmpada sem saber se serão necessárias: Ligar o interruptor; Se a lâmpada não acender, então: o Pegar uma escada; o Posicionar a escada embaixo da lâmpada; o Buscar uma lâmpada nova; o Subir na escada; o Retirar a lâmpada velha; o Colocar a lâmpada nova. Podemos considerar ainda que a lâmpada nova pode não funcionar. Nesse caso devemos trocá-la novamente, quantas vezes forem necessárias, até que a lâmpada acenda: Ligar o interruptor; Se a lâmpada não acender, então: o Pegar uma escada; o Posicionar a escada embaixo da lâmpada; o Buscar uma lâmpada nova; o Subir na escada; o Retirar a lâmpada velha; o Colocar a lâmpada nova; o Se a lâmpada não acender, então: Retirar a lâmpada; Colocar outra lâmpada; Se a lâmpada não acender, então: ... Observamos que o teste da lâmpada nova é efetuado por um conjunto de ações: Se a lâmpada não acender então: o Retire a lâmpada o Coloque outra lâmpada 13 Representação de algoritmos Em vez de escrevermos várias vezes este conjunto de ações, podemos alterar o fluxo sequencial de execução do programa, de forma que, após executar a ação “coloque outra lâmpada”, voltemos a executar a ação “se a lâmpada não acender”. Precisa-se então determinar um limite para tal repetição, para garantir que ela cesse quando a lâmpada finalmente acender: Enquanto a lâmpada não acender, faça: o Retire a lâmpada o Coloque outra lâmpada Uma versão final do algoritmo, que repete ações até alcançar o seu objetivo: trocar a lâmpada queimada por uma que funcione, é apresentada abaixo. Ligar o interruptor; Se a lâmpada não acender, então: o Pegar uma escada; o Posicionar a escada embaixo da lâmpada; o Buscar uma lâmpada nova; o Subir na escada; o Retirar a lâmpada velha; o Colocar a lâmpada nova; o Enquanto a lâmpada não acender, faça: Retirar a lâmpada; Colocar outra lâmpada. Até agora, estamos efetuando a troca de uma única lâmpada. Todo o procedimento poderia ser repetido 10 vezes, por exemplo, no caso de querermos trocar 10 lâmpadas. Inicialmente, tínhamos um pequeno conjunto de ações que deveriam ser executadas (estrutura sequencial). Através de uma condição, incluímos posteriormente uma estrutura de seleção. Na necessidade de repetir um determinado trecho do algoritmo, construiu-se no final uma estrutura de repetição. 14 Representação de algoritmos Representação com fluxograma convencional É uma representação gráfica de algoritmos onde formas geométricas diferentes implicam ações (instruções, comandos) distintas. Tal propriedade facilita o entendimento das ideias contidas nos algoritmos e justifica sua popularidade. Esta forma é aproximadamente intermediária à descrição narrativa e ao pseudocódigo (subitem seguinte), pois é menos imprecisa que a primeira e, no entanto, não se preocupa com detalhes de implementação do programa, como o tipo das variáveis usadas. Nota-se que os fluxogramas convencionais preocupam-se com detalhes de nível físico da implementação do algoritmo. Por exemplo, figuras geométricas diferentes são adotadas para representar operações de saída de dados realizadas em dispositivos distintos, como uma fita magnética ou um monitor de vídeo. A seguir, na Tabela 2.1, são apresentados os símbolos mais comuns utilizados para representação de algoritmos em fluxogramas convencionais. Tabela 2.1 Simbologia básica mais utilizada para representação de algoritmos em fluxograma convencional Terminal - Símbolo utilizado como ponto para indicar o início e/ou fim do fluxo de um programa. Seta de fluxo de dados - permite indicar o sentido do fluxo de dados. Serve exclusivamente para conectar os símbolos ou blocos existentes. Processamento - símbolo ou bloco que se utiliza para indicar cálculos (algoritmos) a efetuar, atribuições de valores ou qualquer manipulação de dados que tenha um bloco específico para sua descrição. Entrada de dados ou operação manual - utilizado para ler os dados necessários ou programa fora de linha sem intervenção de dispositivos mecânicos. Entrada e saída de dados - símbolo em função de dispositivo qualquer de entrada ou saída de dados, como fornecedor de informações para processamento, gravação e outros. Saída de dados em vídeo - utiliza-se este símbolo quando se quer mostrar dados na tela do vídeo. 15 Representação de algoritmos Saída de dados em impressora - é utilizado quando se deseja que os dados sejam impressos. Decisão - indica a decisão que deve ser tomada, indicando a possibilidade de desvios para diversos outros pontos do fluxo, dependendo do resultado de comparação e de acordo com situações variáveis. Conector - utilizado quando é preciso particionar o diagrama. Quando ocorrer mais de uma partição, é colocada uma letra ou número dentro do símbolo de conexão para identificar os pares de ligação. Conector - usado para indicar conexão de fluxo em outra página. De modo geral, um fluxograma se resume a um único símbolo inicial por onde a execução do algoritmo começa, e um ou mais símbolos finais, que são pontos onde a execução do algoritmo se encerra. Partindo do símbolo inicial, há sempre um único caminho orientado a ser seguido, representando a existência de uma única sequencia de execução das instruções. Isto pode ser melhor visualizado pelo fato de que, apesar de vários caminhos poderem convergir para uma mesma figura do diagrama, há sempre um único caminho saindo desta. Exceções a esta regra são os símbolos finais, dos quais não há nenhum fluxo saindo, e os símbolos de decisão, de onde pode haver mais de um caminho de saída (usualmente dois caminhos), representando uma bifurcação no fluxo. Na Figura 2.1, é apresentado um exemplo de fluxograma convencional para calcular a média de quatro notas e verificar se o aluno foi aprovado ou reprovado. Neste caso, o algoritmo faz a leitura das notas N1, N2, N3 e N4, na sequencia calcula a média, por fim verifica se a média foi maior ou igual a sete, se for verdadeiro, escreve “Aprovado”, senão escreve “Reprovado”. 16 Representação de algoritmos Figura 2.1 Exemplo de algoritmo em fluxograma convencional. Representação em Pseudocódigo Os algoritmos são descritos em uma linguagem chamada pseudocódigo, que são independentes das linguagens de programação. Esta forma de representação de algoritmos é rica em detalhes, como a definição dos tipos das variáveis usadas no algoritmo. Por assemelhar-se bastante à forma em que os programas são escritos, encontra muita aceitação. Ao contrário de uma linguagem de programação não existe um formalismo rígido de como deve ser escrito o algoritmo. O algoritmo deve ser fácil de interpretar e fácil de codificar. Ou seja, ele deve ser o intermediário entre a linguagem falada e a linguagem de programação. Na verdade, esta representação é suficientemente geral para permitir a tradução de um algoritmo nela representado para uma linguagem de programação específica seja praticamente direta. A forma geral da representação de um algoritmo na forma de pseudocódigo é a seguinte: 1 2 3 4 5 6 Algoritmo <nome_do_algoritmo> <declaração_de_variáveis> <subalgoritmos> Início <corpo do algoritmo> Fim Temos que: 17 Representação de algoritmos Algoritmo é uma palavra que indica o início da definição de um algoritmo em forma de pseudocódigo. <nome_do_algoritmo> é um nome simbólico dado ao algoritmo com a finalidade de distingui-los dos demais. <declaração_de_variáveis> consiste em uma porção opcional onde são declaradas as variáveis globais usadas no algoritmo principal e, eventualmente, nos subalgoritmos. <subalgoritmos> consiste de uma porção opcional do pseudocódigo onde são definidos os subalgoritmo. Início e Fim são respectivamente as palavras que delimitam o início e o término do conjunto de instruções do corpo do algoritmo. Um exemplo de representação do algoritmo do cálculo da média de um aluno, na forma de um pseudocódigo é mostrado a seguir: 1 2 3 4 5 6 7 8 9 10 11 12 Algoritmo “Calculo Media” Var N1, N2, N3, N4, MEDIA: real Início Leia N1, N2, N3, N4 MEDIA ← (N1 + N2 + N3 + N4) / 4 Se MEDIA >= 7 então Escreva “Aprovado” Senão Escreva “Reprovado” Fim_se Fim Comentários Todo programador deve ter a preocupação com a clareza de seu algoritmo, ou seja, a facilidade com que outras pessoas poderão entender a lógica da resolução de um problema, para entendê-lo e/ou alterá-lo. Os comentários tem um papel fundamental no algoritmo, pois a partir deles são feitas observações, explicações e colocadas outras informações relevantes. Os comentários em um algoritmo devem estar entre chaves “{}”, ou barra dupla “//” no início da linha. Exemplo: 18 Representação de algoritmos {O texto de comentário deve estar entre chaves, neste caso, usa-se chaves quando o comentário excede limite de uma linha}; //Ou com duas barras no início da linha, quando usar apenas uma linha. A seguir, é apresentada a forma de utilização de comentários no algoritmo para cálculo de média de um aluno: 1 2 3 4 5 6 7 8 9 10 11 12 13 Algoritmo ”Calculo Media” //nome do algoritmo Var N1, N2, N3, N4, MEDIA: real //definição das variáveis Início //Início do algoritmo Leia N1, N2, N3, N4 // Faz a leitura das variáveis N1, N2, N3 e N4 MEDIA ← (N1 + N2 + N3 + N4) / 4 { Calcula a média das notas e atribui O valor calculado na variável MEDIA } Se MEDIA >= 7 então //Verifica se a média é maior ou igual a 7 Escreva “Aprovado” //Se o resultado for Verdadeiro Senão Escreva “Reprovado” //Se o resultado for Falso Fim_se Fim //Término do algoritmo Fases de um algoritmo É importante ressaltar que qualquer tarefa que siga determinado padrão pode ser descrita por um algoritmo, como por exemplo: Como fazer uma canjica? Ou então, como calcular a folha de pagamento de uma empresa? Entretanto ao montar um algoritmo, precisamos primeiro dividir o problema apresentado em três fases fundamentais. Onde temos: ENTRADA: São os dados de entrada do algoritmo; PROCESSAMENTO: São os procedimentos utilizados para chegar ao resultado final; SAÍDA: São os dados já processados, gerando uma informação. Na Figura 2.2, podemos visualizar a esquematização das fases de um algoritmo, em que temos inicialmente na fase de entrada, algumas palavras (dados) dispostas de forma aleatória sem nenhuma conexão e sentido que possa ser interpretado por uma pessoa. Na fase do processamento, existe uma organização lógica para que os dados iniciais possam ter alguma representatividade. Por fim, na fase de saída, depois que os dados foram processados, é gerada uma informação que de fato pode ser entendida, pois existe uma conexão no sentido interpretativo as palavras. 19 Representação de algoritmos ENTRADA PROCESSAMENTO SAÍDA Os dados são dispostos: Estruturas lógicas são usadas para organizar o processamento dos dados: A informação é gerada: ROUPA A DE RATO REI O DO O RATO ROEU A ROUPA DO REI DE ROMA ROMA ROEU Figura 2.2 Fases de um algoritmo. Exemplo das fases no Algoritmo Imagine o seguinte problema: Calcular a média final dos alunos da 3ª Série. Os alunos realizarão quatro provas: P1, P2, P3 e P4. Para montar o algoritmo proposto, faremos três perguntas: a) Quais são os dados de entrada? Resposta: Os dados de entrada são P1, P2, P3 e P4. b) Qual será o processamento a ser utilizado? Resposta: O procedimento será somar todos os dados de entrada e dividi-los por 4 (quatro). c) Quais serão os dados de saída? Resposta: O dado de saída será a média final. Depois de respondidas as questões, podemos construir o algoritmo da seguinte forma: Receba a nota da prova1 Receba a nota de prova2 Receba a nota de prova3 Receba a nota da prova4 Some todas as notas e divida o resultado por 4 Mostre o resultado da divisão 20 Representação de algoritmos Teste de Mesa Após desenvolver um algoritmo ele deverá sempre ser testado. Este teste é chamado de “teste de mesa”, que significa seguir as instruções do algoritmo de maneira precisa para verificar se o procedimento utilizado está correto ou não. Tomando como exemplo o algoritmo para cálculo da média de quatro provas, mostrado a seguir: Receba a nota da 1ª prova Receba a nota de 2ª prova Receba a nota de 3ª prova Receba a nota da 4ª prova Some todas as notas e divida o resultado por 4 Mostre o resultado da divisão Inicialmente vamos identificar a ”1ª prova” como P1, a “2ª prova” como P2, a “3ª prova” como P3, a “4ª prova” como P4 e o resultado do cálculo de média entre as quatro provas como “MEDIA”. Com os esses itens identificados, montamos uma tabela contendo uma coluna para cada identificador, como mostrado na Tabela 2.2: Tabela 2.2 Tabela para fazer o teste de mesa P1 P2 P3 P4 MEDIA Para fazer o teste de mesa deste algoritmo, devemos seguir a sequencia de execução, colocando o valor recebido de cada uma das provas na tabela. Quando chegar na instrução “Some todas as notas e divida o resultado por 4”, o resultado deve ser colocado na coluna “MEDIA”. Obviamente que não faz muito sentido utilizar um teste de mesa para um algoritmo pequeno como este, porém em algoritmos mais complexos ele é um instrumento importante para avaliar o valor tomado pelas variáveis em cada instante da execução do algoritmo. 21 Representação de algoritmos Exercícios 1. Identifique os dados de entrada, processamento e saída no algoritmo abaixo: Receba código da peça Receba valor da peça Receba Quantidade de peças Calcule o valor total da peça (Quantidade * Valor da peça) Mostre o código da peça e seu valor total 2. Um homem quer atravessar um rio com um barco que pode carregar a cada viajem, ele mesmo e apenas mais uma de suas três cargas: um lobo, um carneiro e um maço de alfafas. O homem não pode deixar juntos na margem do rio o lobo com o carneiro, nem o carneiro com o maço de alfafas. O que o homem deve fazer para atravessar o rio sem perder nenhuma de suas cargas? 3. Elabore um algoritmo que mova 5 discos de uma torre de Hanói, que consiste em 3 hastes (A-B-C), uma das quais serve de suporte para os cinco discos de tamanhos diferentes (1-2-3-4-5), os menores sobre os maiores. Pode-se mover um disco de cada vez para qualquer haste, sendo que nunca deve ser colocado um disco maior sobre um menor. O objetivo é transferir os cinco discos da haste A para haste C. Mova <disco n> da haste <n1> para haste <n2> 4. Faça um algoritmo para “Calcular o estoque médio de uma peça”, sendo que ESTOQUEMÉDIO = (QUANTIDADE MÍNIMA + QUANTIDADE MÁXIMA) / 2. 22 Tipos de dados 3 Tipos de dados Como visto na unidade 2, os dados fazem parte da fase de entrada de um algoritmo e são essenciais para que haja a informação. Os dados podem representar números, letras, palavras, frases, textos e até valores lógicos. As linguagens de programação trazem os mais diversos tipos de dados, existem tipos específicos para números, texto, imagem, som, arquivos, entre outros. Entretanto, para os algoritmos iremos utilizar apenas os tipos básicos, ou primitivos, que serão suficientes para o desenvolvimento da lógica utilizada na resolução dos problemas propostos, pois o tipo de informação é apenas uma restrição tecnológica, assim o programador tem a liberdade de adicionar novos tipos ao algoritmo, adequando-os para a linguagem de programação a ser utilizada na implementação do algoritmo. Nesta unidade, serão apresentados os tipos primitivos de dados, por serem largamente utilizados e implementados na maioria das linguagens de programação, que são: numéricos, caracteres e lógicos. Numéricos Esse tipo de dados é específico para representação de números, que, dentro da linguagem de programação, poderão ser utilizados para cálculos. Os dados numéricos são divididos basicamente em duas categorias: inteiros e reais. Inteiro O tipo de dados inteiro representa números positivos, negativos e nulo, ocupam 2 bytes na memória do computador, com isso é possível representar um intervalo de -32768 até +32767. Exemplos: -10, 1, 0, 565. Real O tipo de dados real representa os números positivos, negativos e nulo, podem ser inteiros ou fracionários, que possuem casas decimais, ocupam 6 bytes na memória, sendo 23 Tipos de dados possível armazenar dados num intervalo de 2.9 x 10-39 até 1.7 x 1038. Exemplos: -4, 134.34, 0. Alfanuméricos Os dados alfanuméricos são usados especificamente para representar dados que contenham letras e/ou números. Pode, em determinados momentos, conter somente dados numéricos ou somente literais. Se usado somente para armazenamento de números, não poderá ser utilizada para operações matemáticas. Dados alfanuméricos são classificados basicamente em duas categorias: caractere e cadeia. Caractere Esse tipo de dados é utilizado para representar apenas um caractere, que pode ser um número, letra ou símbolo. Para utilizar esse tipo de dados, o caractere deve ser especificado entre aspas simples („‟). No computador, utiliza 1 byte da memória. Exemplo: pode ser usado para representar a abreviação do sexo de uma pessoa, como „M‟ ou „F‟. Cadeia O tipo de dados cadeia, refere-se a um conjunto de caracteres, que pode conter números, letras e/ou símbolos. Para utilizar esse tipo de dados, os caracteres devem ser especificados entre aspas duplas (“”). Podem ocupar entre 1 a 255 bytes na memória de um computador, ou seja, com esse tipo de dados, podemos representar frases de até 255 caracteres. Dados de cadeia de caracteres também são conhecidos como string, literal ou texto. Exemplos: armazenamento do nome de uma pessoa, como “Juca da Silva”, nome de uma cidade, como “Foz do Iguaçu”. Lógicos Dados do tipo lógico são representados apenas como Verdadeiro (true) ou Falso (false). Na memória de um computador, ocupa apenas 1 byte, com isso para representar o 24 Tipos de dados valor lógico verdadeiro, usamos apenas a letra V, e para representar o valor lógico falso, usamos a letra F. Exercícios 1) Classifique os dados especificados abaixo de acordo com seu tipo, assinalando com I os dados do tipo inteiro, com R os reais, com C os caracteres, com S os literais (strings), com L os lógicos e com N aqueles que são inválidos ou não é possível de se definir. (___) 0.21 (___) .V. (___) Verdadeiro (___) 1 (___) +3456 (___) “abc” (___) V (___) “a” (___) F (___) “0.” (___) “+3456” (___) Malu (___) 1% (___) +6786. (___) +54 (___) “Julio” (___) “-0.0” (___) „Melão‟ (___) 1.34 (___) “.F.” (___) “$%dgf435$3f.” (___) .F. (___) „3‟ (___) -0.554 (___) -0.001 (___) „r‟ (___) „-0554‟ 2) Determine qual é o tipo primitivo de informação presente nas sentenças abaixo: a) A placa “Pare!” tinha 2 furos de bala. b) Josefina subiu 5 degraus para pegar uma maçã boa. c) Alberta levou 3 horas e meia para chegar ao hospital onde concebeu uma garota. d) Julia escreveu em sua casa: “Preserve o meio ambiente”, e ficou devendo R$ 20,59 ao vendedor de tintas. e) José recebeu sua 18a medalha na natação por ter alcançado a marca de 57,3 segundos nos 100 metros rasos. 3) Dados os valores abaixo, identifique seu respectivo tipo de dado: “20/07/2011” ______________________________ -1495 ______________________________ 51.3 ______________________________ Verdadeiro ______________________________ „A‟ ______________________________ „85‟ ______________________________ “Falso” ______________________________ 25 Variáveis, Constantes e Expressões 4 Variáveis, Constantes e Expressões Nesta unidade, serão apresentados alguns dos elementos básicos que compõem os algoritmos. Variáveis Variável é a representação simbólica dos elementos de um conjunto de dados. Cada variável corresponde a uma posição de memória, cujo conteúdo pode ser alterado durante a execução de um programa. Embora uma variável possa assumir diferentes valores, ela só pode armazenar um valor a cada instante. Em uma equação matemática (A+B=7), A e B representam as posições de memória que conterão as parcelas da equação. A seguir, na Figura 4.1 é apresentado um exemplo de utilização de variáveis, onde se têm três variáveis que poderiam ter valores diferentes em momentos diferentes. Num dado momento, a variável BASE poderia ter o valor 5 e a variável ALTURA poderia ter o valor 2, neste caso, de acordo com a representação, a variável AREA_RETANGULO receberia o valor 10 (2 x 5). Variáveis AREA_RETANGULO = BASE * ALTURA Figura 4.1 Exemplo utilização de variáveis. As variáveis são identificadas por um nome que é composto de um ou mais caracteres, o primeiro caractere deve ser uma letra ou o caractere “_” (underscore), não poderá conter caracteres especiais (?/‟]^&%$#@) e nem ser uma palavra reservada da linguagem utilizada. Para ser mais específico, os nomes de variáveis devem ser formados por caracteres pertencentes ao conjunto de caracteres {a,b,c,..z,A,B,C,...Z,0,1,2,...,9,_}. Se utilizar mais de uma palavra para compor o nome da variável utilize o “_“ (underscore) para separar as palavras, não se deve utilizar espaços. Dentro de um algoritmo não se pode ter 26 Variáveis, Constantes e Expressões duas variáveis como o mesmo nome, esse identificador deve ser único para cada variável. Estas mesmas regras servem para compor o nome identificador de constantes e funções, que serão vistos nos próximos tópicos. Exemplos de nomes de variáveis: Meu_Nome válido MEU_NOME válido meu_nome válido vArIaVeL válido _Linha válido Exemplo123 válido 23var não válido, começa com número A...B não válido, possui ponto #maior não válido, possui caractere especial no início Um%dois não válido, possui caractere especial no meio Exemplo 123 não válido, possui espaço O nome de uma variável é geralmente escolhido de forma que represente os dados que estão relacionados com a mesma, ou seja, para que se possa ter ideia do que trata o seu conteúdo sem precisar abri-la. Na Tabela 4.1, é apresentado exemplos de identificação das variáveis com o seu respectivo conteúdo: Tabela 4.1 Exemplo de nomes que representem o conteúdo das variáveis NOME DA VARIÁVEL nome idade sexo salario VALOR DA VARIÁVEL “Juca da Silva” 34 „M‟ 3.800,00 Para melhor detalhamento da forma que a variável é referenciada com a memória do computador, vamos pensa-la como uma sequencia finita de caixas, que num dado momento, guardam algum tipo de informação, como número, uma letra, uma palavra, uma frase, ou outro tipo qualquer de informação. O computador, para poder trabalhar como alguma destas informações precisa saber onde, na memória, o dado está localizado. Fisicamente, cada caixa, ou cada posição de memória, possui um endereço, ou seja, um 27 Variáveis, Constantes e Expressões número, que indica onde cada informação está localizada. Este número é representado através da notação hexadecimal, tendo o tamanho de quatro, ou mais bytes. O endereçamento das posições de memória através de números hexadecimais é perfeitamente compreendido pela máquina, mas para nós humanos torna-se uma tarefa complicada. Pensando nisto, as linguagens de computador facilitaram o manuseio, por parte dos usuários, das posições de memória da máquina, permitindo que, ao invés de trabalhar diretamente com os números hexadecimais, fosse possível dar nomes diferentes a cada posição de memória. Tais nomes seriam de livre escolha do usuário. Com este recurso, os usuários ficaram livres dos endereços físicos (números hexadecimais) e passaram a trabalhar com endereços lógicos (nomes dados pelos próprios usuários). Desta forma, a representação do nome lógico da variável referenciado com a posição da física da memória pode ser visualizada na Figura 4.2: Representação da Memória Valor 4 Endereço 3000: 009d 3 2100: 009e “Mara” 009f: 3433 „F‟ 00aa: 4fa0 55 3aaa: 00ab 45.55 11aa: 00ac 4 33ed: 00ad V ae4e: 00ae 2011 11ee: 00af NOME DA VARIÁVEL X Y nome sexo idade valor quantidade cliente ano Figura 4.2 Esquema de representação da ligação lógica entre o nome de uma variável com o endereçamento da memória do comutador. Portanto, podemos dizer que uma variável é uma posição de memória, representada por um nome simbólico (atribuído pelo usuário), a qual contém, num determinado instante, um conjunto de dados. 28 Variáveis, Constantes e Expressões Toda variável deve ser declarada com um nome seguido de um tipo, conforme o seu conteúdo. Se declararmos uma variável como numérica, não poderemos armazenar textos ou valores lógicos. Em português estruturado, utilizaremos a seguinte sintaxe para declaração de variáveis: 1 2 Var <nome da variável> : <tipo de dado> Como exemplo de declaração de variáveis, temos: 1 2 3 4 5 Var nome sexo idade salario : : : : literal caracter inteiro real Constantes Uma constante compreende a mesma ideia de uma variável, mas com um porem, o seu valor não pode variar, isto é, o seu valor será sempre o mesmo, não poderá ser modificado durante a execução do algoritmo. Quando existir a necessidade de mudar o seu valor, isso deverá ser feito no código do algoritmo e não em tempo de execução. Como as constantes são compreendidas como variáveis “fixas”, ela podem ser dos mesmos tipos de dados que as variáveis: numéricos, caracteres ou lógicos. A regra para identificação dos nomes também segue o mesmo padrão das variáveis. Exemplos: a) PI = 3,14 b) NATAL = “25 de dezembro” Toda constante deve ser declarada com um nome seguido de um tipo, conforme o seu conteúdo. Em português estruturado, utilizaremos a seguinte sintaxe para declaração de constantes: 1 2 Var Constante <nome da constante> : <tipo de dado> Como exemplo de declaração de constante, temos: 1 2 3 Var Constante pi : real Constante nascimento : literal 29 Variáveis, Constantes e Expressões Expressões Uma expressão pode ser a combinação de uma ou mais constantes, variáveis, operadores e/ou funções. As expressões mais comuns são as aritméticas que contém os operandos (constantes, variáveis e/ou funções) ligados por um ou mais operadores (+, -, *, /). Exemplos: a) valor * 10 b) salario - imposto c) total - (total * 0,2) d) “Sr. “ + nome Exercícios 1) Assinale com C os identificadores corretos e com I os incorretos. Explique o que está de errado nos identificadores incorretos. (___) valor (___) a1b2c3 (___) “abc” (___) _b248 (___) 3 x 4 (___) km/h (___) nota*do*aluno (___) Maria (___) xyz (___) nome empresa (___) sala_215 (___) ah!0 2) Supondo que as variáveis NB, NA, NMAT e SX sejam utilizadas para armazenar a nota do aluno, o nome do aluno, o número da matrícula e o sexo, declare-as corretamente em pseudocódigo, associando o tipo adequado ao dado que será armazenado. 3) Faça o teste de mesa no diagrama de blocos abaixo e preencha a tabela ao lado com os dados do teste: Início SALARIO ABONO SALNOVO 600,00 60,00 Ler SALARIO 350,00 50,00 Ler ABONO SALNOVO ß SALARIO + ABONO SALNOVO Fim 30 Operações básicas 5 Operações básicas Os operadores são representados por símbolos, funcionando como relacionamentos que criam um único resultado. Existem os operadores aritméticos, relacionais, lógicos e de strings (cadeia de caracteres). Atribuição Essa operação coloca um valor determinado para uma variável ou constante especificada. É importante que o tipo do valor, seja compatível com o tipo da variável, pois na implementação a incompatibilidade irá gerar erros ou resultados inesperados. A atribuição pode ser feita determinando-se diretamente um valor compatível com o tipo de dados da variável ou obtendo-se o através do resultado de uma expressão ou também, com o resultado da execução de uma função, assunto que será abordado adiante. Em algoritmos de Portugol, trataremos as operações de atribuição com o símbolo “”. A seguir são mostrados alguns exemplos de atribuição: a) VARIAVEL_INTEIRO 34 (atribuição direta de número inteiro); b) VARIAVEL_REAL 7.45 (atribuição direta de número real); c) VARIAVEL_CARACTERE „M‟ (atribuição direta de caractere); d) VARIAVEL_CADEIA “Rua Argentina, 3455 – Centro” (atribuição direta de texto); e) TOTAL PRECO * QUANTIDADE (resultado de uma expressão, obtendo-se um valor de número real); f) X raiz(5) (resultado de uma função). Exemplo de um algoritmo que faz a atribuição de valores nas variáveis: 1 2 3 4 5 6 7 8 Algoritmo Atribuicao Var letra : caracter texto : cadeia num_inteiro : inteiro num_real : real Início letra „a‟ 31 Operações básicas 9 10 11 12 texto “Texto de exemplo” num_inteiro 5 num_real 4.67 Fim Operadores Aritméticos Os operadores matemáticos, mostrados na Tabela 5.1, são usados para realizar operações aritméticas com variáveis e constantes, estão em ordem de prioridade (cima para baixo) em que as operações são efetuadas. Tabela 5.1 Operadores aritméticos Operação Exponenciação Multiplicação Divisão Adição Subtração Inteiro de Divisão Resto da Divisão Operador ^ * / + div mod Exemplo de utilização: a) PI * raio; b) A + B – 3 c) 10 mod 2 Operadores Relacionais Os operadores relacionais servem para comparar dois valores de mesmo tipo, e nesta relação poderemos encontrar constantes, variáveis ou expressões. Os operadores relacionais estão apresentados na Tabela 5.2, a seguir: Tabela 5.2 Operadores relacionais Operação Igual a Diferente de Menor que Maior que Operador = <> < > 32 Operações básicas Menor que ou igual a Maior que ou igual a Membro de <= >= in O resultado de uma comparação obtido utilizando-se um operador relacional, sempre será um valor lógico, verdadeiro ou falso. Com isso, é possível fazer a avaliação dos valores de variáveis ou expressões permitindo a execução de comandos específicos para determinados valores de variáveis, pois a variáveis representam instâncias do problema. O uso desses operadores possui uma grande representatividade na elaboração de algoritmos, pois eles serão largamente utilizados para definir o fluxo a ser seguido na solução dos problemas. Geralmente a grande dificuldade no aprendizado de algoritmo, está no domínio do uso desses operadores, pois eles, em conjunto com os comandos de controle de fluxo, irão determinar quais, ou até quando um conjunto de operações será executado diante de determinados valores das variáveis. O conceito de instância do problema vem do fato de que um algoritmo será feito para resolver determinado problema, mas para um mesmo problema poderemos ter valores diferentes e muitas vezes a variação desses valores irá requerer procedimentos diferentes para resolver o problema. Exemplos de utilização: a) 6 > 7 resulta em falso. b) A + B = 5 o resultado poderá ser verdadeiro ou falso, dependendo do valor da expressão A + B, caso o valor de A seja 3 e o valor de B seja 2, então o resultado será verdadeiro. c) 5,73 in N resulta em falso, pois 5,73 não é membro do conjunto dos números naturais. Operadores Lógicos Os operadores lógicos também comparam valores de mesmo tipo para criar uma lógica verdadeira ou falsa, sim ou não, utilizando a lógica booleana. Os operadores lógicos estão apresentados na Tabela 5.3: 33 Operações básicas Tabela 5.3 Operadores lógicos Operação Conjunção Disjunção Negação Exclusão Operador E OU NÃO XOU Uma expressão lógica representa a união de operações relacionais permitindo que o resultado de várias expressões relacionais seja transformado em um único resultado lógico. Vale lembrar-se da lógica matemática, em que os operadores lógicos são: conjunção, disjunção, negação e exclusão. Nessa lógica o resultado das expressões seguem as seguintes regas: a) O operador E (conjunção) somente retornará o valor verdadeiro se todas as expressões relacionais também retornem valores verdadeiros, ou seja, basta que uma expressão relacional seja falsa para que o resultado geral da expressão também seja falso. b) O operador OU (disjunção) somente retornará falso caso todas as expressões relacionais também sejam falsas, pois basta que uma expressão relacional seja verdadeira para o resultado geral ser verdadeiro. c) O operador NÃO (negação) inverte o valor lógico de verdade para falso e de falso para verdade. d) O operador XOU (exclusão) será verdade se e somente se uma das expressões relacionais for verdadeira. É conhecido como OU exclusivo. Quando ocorrer de numa mesma expressão lógica existir operadores de conjunção e disjunção, devemos resolvê-la da esquerda para a direita, respeitando o uso de parênteses e computar o resultado final. Exemplos de utilização. Admitindo que a variável A armazene o valor 5 e a variável B o valor 3, temos que: a) (A > 4 E B > 4) expressão Falsa b) (A > 4 OU B > 4) expressão Verdadeira c) (NÃO A > 4) expressão Falsa d) (A > 4) expressão Verdadeira 34 Operações básicas e) (A > 4 XOU B < 4) expressão Falsa f) (A > 4 XOU B > 4) expressão Verdadeira No item a, será verdadeiro se, somente se, as duas questões forem verdadeiras. O operador lógico OU retornará verdadeiro se pelo menos uma das duas operações for verdadeira. Para o operador de negação, o que teremos é o inverso da operação analisada. O operador XOU retorna verdadeiro se um operando for verdadeiro e o outro falso. Na tabela verdade, mostrada a seguir (Tabela 5.4), temos o valor de duas proposições p e q, que apresentam todas as possibilidades de valores que elas podem assumir durante a execução de um programa. Na tabela verdade também são apresentadas as expressões de operação lógica E, OU, NÃO e XOU entre as duas proposições, e mostrados os valores que pode se ter de resultado em cada instante. Tabela 5.4 Tabela verdade p V V F F q V F V F pEq V F F F p OU q V V V F NÃO p F F V V NÃO q F V F V p XOU q F V V F Para exemplificar a utilização da tabela verdade, vamos imaginar que o seu pai faça a seguinte promessa para você: “Se você for aprovado no vestibular, eu comprarei um carro e uma moto”. Diante dessa afirmativa, podemos separá-la em duas proposições p e q, onde a proposição p seria “meu pai vai comprar um carro” e a proposição q seria “meu pai vai comprar uma moto”. Para que a promessa feita pelo seu pai seja verdadeira, as duas proposições p e q devem ser verdadeiras, ou seja, ele deve comprar um carro e uma moto. Se o pai comprar apenas o carro, ou apenas a moto, ele não estaria cumprindo a promessa. Porém, se o pai mudasse o conectivo “e” para “ou” na promessa que fez, ficaria assim: “Se você for aprovado no vestibular, eu comprarei um carro ou uma moto”. Portanto, se o pai comprar qualquer um dos dois, o carro ou a moto, a promessa seria cumprida, assim como se ele comprar os dois juntos, a promessa também seria verdadeira. Entretanto, se a promessa sofresse mais uma alteração, adicionando mais um conectivo “ou”, ela ficaria assim: “Se você for aprovado no vestibular, eu comprarei ou um carro, ou uma moto”. Perceba que nesse caso, temos uma exclusividade na promessa feita, em que o pai irá 35 Operações básicas comprar apenas um dos dois, ou o carro, ou a moto. Portanto, a promessa só será verdadeira se apenas um dos dois itens for comprado, sendo falsa se o pai comprar os dois itens ou não comprar pelo menos um item. Para exemplificar a utilização de operações lógicas, como geralmente utilizadas em programação, faremos a resolução de uma expressão lógica um pouco mais complexa, usando vários operadores lógicos, mostrado a seguir. Neste caso, comecemos resolvendo as expressões que estão dentro dos parênteses, respeitando a prioridade, e na ordem da esquerda para a direita: 1º passo: NÃO((A > 4) E (B > 4)) OU A <= 5 (expressão inicial) 2º passo: NÃO( .V. E .F.) OU .V. (resolve-se as expressões A>4, B>4 e A<=5) 3º passo: NÃO(.F.) OU .V. (resolve-se .V. E .F.) 4º passo: .V. OU .V. (resolve-se NÃO(.F.)) 5º passo: .V. (por fim, resolve-se .V. OU .V., chegando ao resultado .V. para a expressão completa). Operador de caractere O operador de strings é representado pelo sinal de adição (+), é utilizado para combinar duas ou mais séries de caracteres. Supondo que A e B são variáveis do tipo caractere, a expressão A+B resultaria um único literal formado pelo conteúdo de A seguido do conteúdo de B. Como exemplo, suponhamos que: A = “Charles Babbage é “ B = “conhecido como “ C = “o pai do computador.” Teremos: A + C = “Charles Babbage é o pai do computador” A + B + C = “Charles Babbage é conhecido como o pai do computador” Portanto, o operador “+” caso seja usado entre variáveis do tipo CHAR ou STRING, causará uma ação conhecida por concatenação, ou seja, juntar os caracteres ou STRING‟s usados na operação em uma só STRING. 36 Operações básicas Exemplo de um algoritmo que faz a concatenação de caracteres e strings: 1 2 3 4 5 6 7 8 9 10 11 Algoritmo Concatena Var Letra1, Letra2 : caracter Nome1, Nome2, Nome : cadeia Início Letra1 „D‟ Letra2 „a‟ Nome1 “Joao” Nome2 “Silva” Nome Nome1 + Letra1 + Letra2 Fim + Nome2 As instruções acima resultarão no armazenamento de uma string “João Da Silva” na variável rotulada de “Nome”. Prioridade de Operadores Durante a execução de uma expressão que envolve vários operadores, é necessária a existência de prioridades representando um padrão a ser seguido, pois, caso contrário poderá se obter valores que não representam o resultado esperado. Utilizaremos a prioridade de operadores definida abaixo pela simplicidade e compatibilidade com a maioria das linguagens, mas as linguagens de programação apresentam pequenas variações nessas prioridades: 1º - Operações embutidas em parênteses “mais internos”; 2º - Funções (Quociente, Resto, Potência e Funções Primitivas); 3º - Multiplicação e/ou divisão; 4º - Adição e/ou Subtração; 5º - Operadores Relacionais; 6º - Operadores Lógicos. 37 Operações básicas Exercícios 1) Indique qual o será o resultado obtido das seguintes expressões: a. 1 / 2 b. 1 DIV 2 c. 1 MOD 2 d. ( 200 DIV 10 ) MOD 4 e. 5 ** 2 + 3 f. 6 + 19 - 23 g. 3,0 * 5,0 + 1 h. 1 / 4 + 2 i. 29,0 / 7 + 4 j. 3 / 6,0 - 7 2) Indique o resultado das seguintes expressões: a. 2 > 3 b. ( 6 < 8 ) OR ( 3 > 7 ) c. ((( 10 DIV 2 ) MOD 6 ) > 5 ) XOR ( 3 < ( 2 MOD 2 ) ) d. NOT ( 2 < 3 ) 3) Escreva o comando de atribuição e resolva a expressão das seguintes formulas matemáticas. a. b. B C onde A= 2, B= 6, C = 3, D=4, E=8, F=4 X E D F 2 2 X 3 X X 1 X 1 2 X Y onde X = 2 X 2 A 4) Construa o algoritmo que calcule as seguintes expressões: a. 2 + 3 * { 23 - 12 + [ { ( 123 / 34 ) + 10 } / 2 - 1 * ( 45 - 12 ) ] / 3 } b. [ ( 2 * 3 ) ^2 - 1 ] ^ 4 c. ( 2 + [ 2 * 3 - ( 4 / 20 ) ^ 2 ] )/ (10 * { [ ( 7 * 3 ) - 2 ] ^ 3 }) 5) Dadas as variáveis X = 2, Y = 5, Z = 9, NOME = "Leila" e Flag = FALSO, indique os resultados das expressões abaixo: a. (X + Y > Z) e NOME = "JOSÉ" b. Flag ou (Y ≠ X) c. não Flag e (Z div Y) + 1 = X) d. (NOME = "Leila") e Flag ou (Raiz(X,2) < Z + 10) 6) É correto definir uma variável como sendo caracter e atribuirmos a ela o valor: „PEDRO‟? E se a variável fosse definida como literal, a mesma poderia receber um 38 Operações básicas valor do tipo caracter? 7) Identifique o(s) erro(s) encontrados no algoritmo seguinte: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 8) Algoritmo Exercício Var Maria : literal idade : inteiro letra : caracter Maria : real Início idade 23 idade 678 idade letra letra ABC letra A letra 2 Fim Qual a diferença existente nas seguintes atribuições? a. Letra „A‟ Nome „João‟ b. Letra A Nome João 39 Entrada e Saída de dados 6 Entrada e Saída de dados Na unidade que trata das fases de um algoritmo, foram abordados duas fases importantes: a fase de entrada dos dados e a fase de saída, que por sua vez apresenta a informação. No ambiente computacional, os objetos processados são as variáveis, sabemos que um programa tem como principal objetivo a resolução de problemas do mundo real. Desta forma, num algoritmo será preciso representar a troca de informações que ocorrerá entre o mundo do computacional e o mundo real. Para isso, devemos utilizar comandos de entrada e saída, onde esses comandos irão indicar que determinadas variáveis receberão valores, os quais serão informados por um indivíduo do meio externo ou que os valores de determinadas variáveis ou expressões serão enviados para o meio externo. Em nível de algoritmo esses comandos representam apenas a entrada e a saída da informação, independe do dispositivo utilizado (teclado, discos, impressora, monitor, entre outros), pois para a lógica da solução do problema basta saber que informação esta entrando e saindo. Mas no mundo da programação esse meio externo é representado pelos periféricos de entrada e saída e as linguagens de programação possuem comandos específicos para cada tipo de unidade de Entrada/Saída, mas, em algoritmos não teremos essa preocupação. Comando de entrada de dados Em algoritmos, a entrada de dados é feita com o comando “Leia”, no qual são especificadas as variáveis que receberão os valores. No caso da execução do comando “Leia X”, a valor recebido do meio externo deve ser armazenado na variável X. O comando Leia também pode ser executado como “Leia X, Y, Z”, neste caso, seria recebido ao mesmo tempo do meio externo, três variáveis, e os valores seriam armazenados na sequencialmente nas variáveis X, Y e Z. Exemplo de um algoritmo para fazer a leitura de dados: 1 2 Algoritmo Ler_dados Var nome : cadeia 40 Entrada e Saída de dados 3 4 5 6 7 8 9 idade : inteiro X, X, Z : real Início Leia nome Leia idade Leia X, Y, Z Fim Comando de saída de dados A saída de dados em algoritmos é feita através do comando “Escreva”. A sintaxe do comando Escreva, funciona de forma parecida com a sintaxe do comando Leia, pois logo após o comando deve ser colocado as variáveis que devem ser apresentadas ao meio externo, como exemplo “Escreva X, Y, Z”. Neste caso, se as variáveis X, Y e Z tivessem valores 40, 50 e 60 consecutivamente, para o usuário que executou o algoritmo implementado no computador, seria apresentado como “405060”. Sendo assim, essa informação ficou um tanto complicada de se entender, pois daria margem à ambiguidade de interpretação dos valores, por exemplo, o usuário não saberia distinguir qual daqueles números é o valor de Y. Entretanto, o comando Escreva também permite escrever textos diretamente, sem uso de variáveis, com isso é possível fazer operações de concatenação textos com o conteúdo de variáveis. Tomando por base as variáveis X, Y e Z, imaginando que elas correspondem a valores de cada um dos vértices de um triângulo, poderíamos informar detalhadamente ao usuário, o valor da variável e qual vértice ela corresponde. Quando quisermos colocar um texto diretamente no comando, devemos especificá-lo entre aspas duplas (“”), como nos exemplos a seguir: a) Escreva “O vértice X tem valor: “ + X (a saída seria: “O vértice X tem valor: 40”); b) Escreva “O vértice Y tem valor: “ + Y (a saída seria: “O vértice Y tem valor: 50”); c) Escreva “O triângulo tem os valores: X=” + X + “, Y=” + Y +”, Z=” + Z (a saída seria: “O triângulo tem os valores: X=40, Y=50, Z=60”). Exemplo de um algoritmo para fazer a leitura de dados: 1 2 3 Algoritmo Escrever_dados Var nome : cadeia idade : inteiro 41 Entrada e Saída de dados 4 5 6 7 8 9 10 Início Escreva “Informe o seu nome: “ Leia nome Escreva “Informe a sua idade: “ Leia idade Escreva “Obrigado “ + nome + “. Você tem “ + idade + “ anos.” Fim Exercícios 1) Faça um algoritmo para ler três números inteiros e escrever a média dos números lidos. 2) Faça um algoritmo para ler os coeficiente de uma equação do segundo grau e escrever o valor do seu Delta. 3) Faça um algoritmo para ler os catetos de um triângulo retângulo e escrever a sua hipotenusa. 4) Faça um algoritmo para ler uma temperatura em graus Celsius e transformá-la em farenheit. Utilize a seguinte fórmula: F = (180(C + 32)) / 100. 5) Faça um algoritmo para ler o preço de compra e o percentual de lucro desejado por um vendedor e calcular o preço de venda. 6) Faça um algoritmo para ler duas variáveis inteiras e trocar o seu conteúdo. 7) Faça um algoritmo para ler o horário de entrada e saída de um cliente na fila de um banco e seguida calcular o tempo de permanência do cliente na fila. Cada horário será lido em duas variáveis inteiras representando a hora e os minutos. A resposta deve ser dada em horas (ex. 3:10). 8) Faça um algoritmo para ler o valor do saque realizado pelo cliente de um banco e escrever quantas notas de cada valor serão necessárias para atender ao saque com a menor quantidade de notas possível. Serão utilizadas notas de 100, 50, 20, 5 e 1 reais. 9) Faca um algoritmo para ler o horário (hora, min e seg) de inicio e a duração, em segundos, de uma experiência biológica, em seguida informar o horário (hora, min, seg) de termino da mesma. 10) Faça um algoritmo para ler as seguintes informações de uma pessoa: Nome, Idade, Sexo, Peso, Altura, Profissão, Rua, Bairro, Cidade, Estado, CEP, Telefone. 42 Entrada e Saída de dados 11) Dado as seguintes informações de um funcionário: Nome, idade cargo e o seu salário bruto considere: c. O salário bruto teve um reajuste de 38%. d. O funcionário receberá uma gratificação de 20% do salário bruto. e. O Salário total é descontado em 15%. Faça um algoritmo e um algoritmo para: Imprimir Nome, idade e cargo. Imprimir o salário bruto. Imprimir o salário líquido. 12) Faça um algoritmo para ler a base e a altura de um triângulo. Em seguida, escreva a área do mesmo. Obs.: Área = ( Base * Altura ) / 2 13) Faça um algoritmo para: a. Ler uma CADEIA em forma de data. Exemplo : „26/09/95‟. b. Escrever o dia, mês e ano desta data. 14) Uma empresa tem para um determinado funcionário uma ficha contendo o nome, número de horas trabalhadas e o n0 de dependentes de um funcionário. Considerando que: a. A empresa paga 12 reais por hora e 40 reais por dependentes. b. Sobre o salário são feito descontos de 8,5% para o INSS e 5% para IR. Faça um algoritmo para ler o Nome, número de horas trabalhadas e número de dependentes de um funcionário. Após a leitura, escreva qual o Nome, salário bruto, os valores descontados para cada tipo de imposto e finalmente qual o salário líquido do funcionário. 15) O preço de um automóvel é calculado pela soma do preço de fábrica com o preço dos impostos (45% do preço de fábrica) e a percentagem do revendedor (28% do preço de fábrica). Faça um algoritmo que leia o nome do automóvel e o preço de fábrica e imprima o nome do automóvel e o preço final. 43 Processos de Seleção 7 Processos de Seleção Até o momento, os algoritmos demonstrados foram executados numa sequencia linear, seguindo-se as ações de cima para baixo, sem que haja desvio ou seleção de código a ser executado. Nesta unidade, veremos sobre as estruturas condicionais. Elas são processos de seleção que permitem a escolha de ações serem executadas quando determinada condição for ou não satisfeita. As estruturas condicionais abordadas são: “Se-Então-Senão” e “Escolha-Caso”. Estrutura SE-ENTÃO-SENÃO (IF-THEN-ELSE) A estrutura de seleção SE, é usada para tomar decisões, ou seja, desviar a execução do algoritmo de acordo com uma determinada condição, podendo ser simples ou composta. O comando SE é utilizado quando há a necessidade de avaliar o valor de variáveis ou expressões e de acordo com o resultado dessa análise executar um conjunto específico de comandos. A análise da condição especificada para a estrutura SE, sempre será feita com base em valores lógicos (booleanos), ou seja, ela sempre analisará se a condição é verdadeira ou falsa. A estrutura SE, quando organizada de forma simples, faz um desvio de execução somente se uma a condição for verdadeira, ignorando o desvio quando a condição for falsa. Essa estrutura simples é organizada da seguinte forma: Se <condição> Então <comandos> Fim_se O item <condição> deve ser substituído pela expressão lógica que será avaliada, então, se o resultado da expressão lógica for verdadeiro, serão executados os comandos especificados no lugar de <comandos>. Um exemplo da estrutura SE, com analogia ao mundo real, pode ser entendida como: Se não chover, então Vou à praia. Percebe-se que a condição avaliada é “não chover” e a ação praticada é “ir à praia”, portanto, eu irei à praia somente se a condição for verdadeira, ou seja, somente se não chover. 44 Processos de Seleção Vejamos o exemplo de um algoritmo que faz uso estrutura SE, tendo como enunciado “faça um algoritmo que leia um valor inteiro, referente a idade de uma pessoa, e imprima uma mensagem informando que ela pode votar somente se tiver 16 anos ou mais”: 1 2 3 4 5 6 7 8 9 10 Algoritmo “Verifica Idade - 1” Var idade : inteiro Início Escreva “Informe a sua idade: “ Leia idade Se idade >= 16 Então Escreva “Você pode votar!” Fim_se Fim Na Figura 7.1, podemos visualizar graficamente o fluxo de execução da estrutura sequencial do algoritmo “Verifica idade – 1”. Figura 7.1 Fluxograma do algoritmo “Verifica idade – 1”. Com a estrutura SE simples, vimos que é possível fazer um desvio condicional somente se a condição analisada resultar em um valor lógico verdadeiro. Com a estrutura SE composta, podemos fazer, além do desvio para quando a condição for verdadeira, também um desvio condicional quando a expressão analisada resultar no valor lógico falso. Essa estrutura composta é organizada da seguinte forma: Se <condição> Então <comandos quando a condição for verdadeira> Senão <comandos quando a condição for falsa> Fim_se 45 Processos de Seleção Neste caso, quando a condição analisada resultar no valor lógico falso, serão executados os comandos que estão logo abaixo do desvio “Senão”. Continuando a analogia ao mundo real, a frase pode ser complementada da seguinte forma: Se não chover, então Vou à praia, senão vou ao shopping. Portanto, se a condição “não chover” for avaliada e resultar no valor lógico verdadeiro, então eu poderei ir à praia, mas, se a condição resultar no valor lógico falso, ou seja, se estiver chovendo, então eu irei ao shopping. Na sequencia, é apresentado o mesmo exemplo de algoritmo mostrado anteriormente, mas com uma modificação no enunciado para que seja usado uma estrutura SE composta. Sendo, “faça um algoritmo que leia um valor inteiro, referente a idade de uma pessoa, e imprima uma mensagem informando que ela pode votar somente se tiver 16 anos ou mais, caso contrário informe que ela não pode votar”: 1 2 3 4 5 6 7 8 9 10 11 12 Algoritmo “Verifica idade - 2” Var idade : inteiro Início Escreva “Informe a sua idade: “ Leia idade Se idade >= 16 Então Escreva “Você pode votar!” Senão Escreva “Você não pode votar!” Fim_se Fim Na Figura 7.2, podemos visualizar graficamente o fluxo de execução da estrutura sequencial do algoritmo “Verifica idade – 2”. Figura 7.2 Fluxograma do algoritmo “Verifica idade – 2”. 46 Processos de Seleção Exercícios: Se-Então-Senão 1) Faça um algoritmo para ler um número inteiro e informar se este é maior que 10. 2) Faça um algoritmo para ler dois números inteiros e informar se estes números são iguais ou diferentes. 3) Faça um algoritmo para ler um número inteiro e informar se o número é par ou ímpar. 4) Faça um algoritmo para ler dois números inteiros A e B e informar se A é divisível por B. 5) Faça um algoritmo para ler dois números inteiros e escrever o maior. 6) Faça um algoritmo para ler dois números inteiros e escrevê-los em ordem crescente. 7) Faça um algoritmo para ler duas variáveis inteiras A e B e garantir que A e B fiquem em ordem crescente, ou seja, a variável deverá armazenar o menor valor fornecido e a variável B o maior. 8) Faça um algoritmo para ler os coeficiente de uma equação do segundo grau e escrever as suas raízes. 9) Elabore um algoritmo para testar se uma senha digita é igual a “Patinho Feio”. Se a senha estiver correta escreva “Acesso permitido”, do contrario emita a mensagem “Você não tem acesso ao sistema”. 10) Faça um algoritmo para ler três valores reais e informar se estes podem ou não formar os lados de um triângulo e qual tipo de triângulo seria: equilátero, isósceles ou escaleno. 11) Faça um algoritmo para ler três números positivos e escrevê-los em ordem crescente. 12) Faça um algoritmo para ler o nome, as três notas e o número de faltas de um aluno e escrever qual a sua situação final: Aprovado, Reprovado por Falta ou Reprovado por Média. A média para aprovação é 5,0 e o limite de faltas é 27. A reprovação por falta sobrepõe a reprovação por Média. 13) Elabore um algoritmo que indique se um número digitado está compreendido entre 20 e 90, ou não. 14) Um comerciante comprou um produto e quer vendê-lo com um lucro de 45% se o valor da compra for menor que R$ 20,00; caso contrário, o lucro será de 30%. Elabore um algoritmo que leia o valor do produto e imprima o valor de venda para o produto. 47 Processos de Seleção 15) Faça um algoritmo para ler um salário e atualizá-lo de acordo com a tabela abaixo. Faixa salarial Aumento até 600,00 30% 600,01 a 1.100,00 25% 1100,01 a 2.400,00 20% 2400,01 a 3.550,00 15% Acima de 3.550,00 10% Estrutura SELECIONE-CASO (SWITCH-CASE) A estrutura de decisão CASO-SELECIONE é utilizada para testar, na condição, uma única expressão, que produz um resultado, ou, então, o valor de uma variável, em que está armazenado um determinado conteúdo. Compara-se, então, o resultado obtido no teste com os valores fornecidos em cada cláusula “Caso”. A estrutura Caso, contém uma expressão (o seletor) e uma lista de declarações, cada declaração é anteposta por uma ou mais constantes (chamadas constantes de caso) ou com a palavra Senão. O seletor deve ser de um tipo ordinal, ou seja, possua uma ordem. Todas as constantes de caso devem ser diferentes e de um tipo ordinal compatível com o tipo do seletor. Esta estrutura executa uma sequencia de comandos precedida pela constante igual ao valor do seletor. Se nenhuma constante for igual ao valor do seletor, a parte Senão será executada. Se não houver a parte Senão, a execução continuará com o próximo comando que segue a estrutura Caso no algoritmo. A estrutura de decisão Caso é organizada da seguinte forma: Selecione <expressão> Caso <valor1> Faça <comando> Caso <valor2> Faça <comando> Caso <valor3> Faça <comando> Senão <comando> Fim_selecione A seguir, é mostrado um algoritmo que implementa uma estrutura Selecione-Caso, tendo como enunciado “faça um algoritmo que leia um valor inteiro, de 1 a 7, referente aos dias da semana, em seguida imprima o nome do dia, caso o numero for diferente deste intervalo, informar que o dia é inválido”: 48 Processos de Seleção 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Algoritmo “Verifica_Dia_Semana” Var dia : inteiro Início Escreva “Informe o dia da semana (1 a 7): “ Leia dia Selecione dia Caso 1 Faça Escreva “Domingo” Caso 2 Faça Escreva “Segunda-feira” Caso 3 Faça Escreva “Terça-feira” Caso 4 Faça Escreva “Quarta-feira” Caso 5 Faça Escreva “Quinta-feira” Caso 6 Faça Escreva “Sexta-feira” Caso 7 Faça Escreva “Sábado” Senão Escreva “Dia inválido!” Fim_selecione Fim Exercícios: Selecione-Caso 1) Recebidos valores numéricos entre zero e cinco, escreva-os na forma literal. 2) A partir do exercício anterior, pergunte ao usuário se deseja os numerais em inglês ou português. 3) Criar um algoritmo que leia dois números inteiros, e que solicite ao usuário qual a operação deseja realizar entre esses números. Caso o usuário digitar o caractere “*” será realizada uma multiplicação, caso seja digitado o caractere “/” será realizada uma divisão, caso seja digitado o caractere “+” será realizado uma adição, e caso seja digitado o caractere “–” será realizada uma subtração. 4) Elabore um algoritmo que leia um número inteiro entre 1 e 12 e imprima o mês correspondente. Caso seja digitado um valor fora desse intervalo, deverá ser exibida uma mensagem informando que não existe mês com esse número. 49 Processos de Repetição 8 Processos de Repetição Serve para efetuar um conjunto de ações repetidas vezes. Assim como as seleções serviam para tomar decisões permitindo executar uma sequência específica, os comandos de repetição servem para indicar se uma sequência deve continuar sendo executada, permitindo resolver problemas que necessitem que uma determinada sequência seja executada várias vezes até que o resultado esperado seja obtido. Esse recurso vai ampliar bastante o leque de problemas que podem ser resolvidos através de algoritmo/programas, pois a grande maioria dos problemas do mundo real exigem iteratividade e isso representa a grande vantagem no uso dos computadores para resolver problemas do nosso mundo, pois o mundo da máquina é extremamente rápido e nesse tipo de problema há uma grande disparidade no tempo de resolução entre os métodos convencionais e os computacionais. Estrutura de repetição ENQUANTO-FAÇA (WHILE-DO) A estrutura Enquanto-Faça, contém uma condição que controla a execução repetidas vezes de uma sequencia de comandos. A condição que controla a repetição deve ser de tipo lógico (booleano). Ela é avaliada antes da sequencia de comandos ser executada. A sequencia de comandos será executada repetidamente contanto que a condição seja verdadeira. Se a condição no princípio for falsa, a sequencia de comandos não será executada em nada, passando o controle para a linha seguinte a FimEnquanto. A organização da estrutura Enquanto-Faça é feita da seguinte forma: Enquanto <condição> Faça <sequencia de comandos> Fim_enquanto Podemos fazer uso de uma instrução chamada “Interrompa” para interromper o laço de repetição, é usado quando se deseja parar o laço de repetição depois de avaliar uma determinada condição e esta for satisfeita, mostrado a seguir: 50 Processos de Repetição Enquanto <condição1> Faça <sequencia de comandos> Se <condição2> Então {se a condição2 for verdadeira interrompe loop} Interrompa {comando de interrupção opcional} Fim_se <sequencia de comandos> Fim_enquanto Nesta estrutura, é possível verificar que podemos utilizar outros tipos de estruturas dentro de uma estrutura de repetição, esta situação é comum para qualquer tipo de estrutura. O comando Interrompa, força um salto, na sequencia, para os comandos que estão logo após a expressão FimEnquanto, e seu uso não é obrigatório. Estrutura de repetição REPITA-ATÉ QUE (REPEAT UNTIL) A estrutura Repita-Até que, é um tipo de repetição indeterminada com validação final, contém uma condição que controla a execução repetidas vezes de uma sequencia de comandos. A sequencia de comandos será executada até que a condição seja satisfeita, com isso, os comandos serão primeiramente executados e depois será avaliada a condição. Esta condição, depois de avaliada, deve produzir um resultado do tipo lógico. Portanto, a sequencia de comandos será executada pelo menos uma vez, se a condição avaliada for verdadeira, então prossegue-se com mais um repetição, até que a condição avaliada seja falsa. Repita <sequencia de comandos> Até que <condição> A seguir, é apresentado um algoritmo que faz a implementação de uma estrutura Repita-Até que, tendo como enunciado “faça um algoritmo que leia um valor e imprima sua tabuada, esse processo deve ser feito repetidas vezes até que o valor zero seja informado”: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Algoritmo “tabuada” Var num : inteiro Início Repita Escreva “Informe um número: Leia num Escreva “1 x “, num, “ = “, Escreva “2 x “, num, “ = “, Escreva “3 x “, num, “ = “, Escreva “4 x “, num, “ = “, Escreva “5 x “, num, “ = “, Escreva “6 x “, num, “ = “, Escreva “7 x “, num, “ = “, Escreva “8 x “, num, “ = “, “ num*1 num*2 num*3 num*4 num*5 num*6 num*7 num*8 51 Processos de Repetição 16 17 18 19 Escreva “9 x “, num, “ = “, num*9 Escreva “10 x “, num, “ = “, num*10 Até que num <> 0 Fim Estrutura de repetição PARA-FAÇA (FOR-TO-DO) A estrutura de repetição Para-Faça é uma estrutura determinada, usada quando se deseja que uma sequencia de comandos seja executada por um número N de vezes. Nessa estrutura de repetição, também envolve a avaliação de uma condição. Na repetição determinada o algoritmo apresenta previamente a quantidade de repetições. Esta estrutura repete uma sequencia de comandos em um determinado número de vezes, sendo especificada a condição inicial e a final. Para <variável> de <valor-inicial> ate <valor-limite> [passo <incremento>] faça <sequencia de comandos> Fim_para Os itens <valor-inicial>, <valor-limite> e <incremento> são avaliados uma única vez antes da execução da primeira repetição, e não se alteram durante a execução do laço, mesmo que variáveis eventualmente presentes nessas expressões tenham seus valores alterados. A cada interação do laço, é incrementado um valor na variável. 1 2 3 4 5 6 7 8 9 10 Algoritmo “tabuada” Var num, cont : inteiro Início Escreva “Informe um número: “ Leia num Para cont De 1 até 10 Passo 1 Faça Escreva cont, “ x “, num, “ = “, num * cont Fim_para Fim 52 Modularização 9 Modularização A modularização consiste num método utilizado para facilitar a construção de grandes algoritmos, através de sua divisão em pequenas etapas, que são os módulos ou subalgoritmos. A primeira delas, por onde começa a execução do trabalho, recebe o nome de algoritmo principal, e as outras são os subalgoritmos propriamente ditos, que são executados sempre que ocorre uma chamada dos mesmos, o que é feito através da especificação de seus nomes. A complexidade dos algoritmos está intimamente ligada à da aplicação a que se destinam. Em geral, problemas complicados exigem algoritmos extensos para sua solução. Sempre é possível dividir problemas grandes e complicados em problemas menores e de solução mais simples. Assim, pode-se solucionar cada um destes pequenos problemas separadamente, criando algoritmos para tal (subalgoritmos). Posteriormente, pela justaposição destes subalgoritmos elabora-se “automaticamente” um algoritmo mais complexo e que soluciona o problema original. Esta metodologia de trabalho é conhecida como “Método de Refinamentos Sucessivos”, cujo estudo é assunto de cursos avançados sobre técnicas de programação. Um subalgoritmo é um nome dado a um trecho de um algoritmo mais complexo e que, em geral, encerra em si próprio um pedaço da solução de um problema maior – o algoritmo a que ele está subordinado. Em resumo, os subalgoritmos são importantes na: subdivisão de algoritmos complexos, facilitando o seu entendimento; estruturação de algoritmos, facilitando principalmente a detecção de erros e a documentação de sistemas; e modularização de sistemas, que facilita a manutenção de softwares e a reutilização de subalgoritmos já implementados. A ideia da reutilização de software tem sido adotada por muitos grupos de desenvolvimento de sistemas de computador, devido à economia de tempo e trabalho que 53 Modularização proporcionam. Seu princípio é o seguinte: um conjunto de algoritmos destinado a solucionar uma série de tarefas bastante corriqueiras é desenvolvido e vai sendo aumentado com o passar do tempo, com o acréscimo de novos algoritmos. A este conjunto dá-se o nome de biblioteca. No desenvolvimento de novos sistemas, procura-se ao máximo basear sua concepção em subalgoritmos já existentes na biblioteca, de modo que a quantidade de software realmente novo que deve ser desenvolvido é minimizada. Portanto, com a utilização de subalgoritmos, podemos reduzir a quantidade de comandos que são usados repetidas vezes num algoritmo, para executar determinada tarefa. Nestes casos, os subalgoritmos proporcionam uma diminuição do tamanho de algoritmos maiores. Nesta unidade, serão apresentados dois conceitos de subalgoritmos utilizados no desenvolvimento de algoritmos, que são os procedimentos e as funções. Mecanismo de Funcionamento Um algoritmo completo é composto por um algoritmo principal e diversos subalgoritmos (tantos quantos forem necessários e/ou convenientes). O algoritmo principal é aquele por onde a execução do algoritmo sempre se inicia. Este pode eventualmente invocar os demais subalgoritmos, como representado na Figura 9.1. Algoritmo principal … subalgoritmo 1 … subalgoritmo 2 … subalgoritmo 1 … … subalgoritmo 2 … … Figura 9.1 Representação dos subalgoritmos. Durante a execução do algoritmo principal, quando se encontra um comando de invocação de um subalgoritmo, a execução do mesmo é interrompida. A seguir, passa-se à execução dos comandos do corpo do subalgoritmo. Ao seu término, retoma-se a execução do algoritmo que o chamou (no caso, o algoritmo principal) no ponto onde foi 54 Modularização interrompida (comando de chamada do subalgoritmo) e prossegue-se pela instrução imediatamente seguinte. Além disso, é possível que um subalgoritmo chame outro através do mesmo mecanismo. Na representação em pseudocódigo, o corpo do algoritmo principal é sempre o último trecho a ser escrito no algoritmo. As definições dos subalgoritmos estão sempre colocadas no trecho após a definição das variáveis globais e antes do corpo do algoritmo principal: 1 2 3 4 5 6 Algoritmo <nome do algoritmo> Var <definição das variáveis globais> <definições dos subalgoritmos> Inicio <corpo do algoritmo principal> Fim Definição de Subalgoritmos A definição de um subalgoritmo consta de: um cabeçalho, onde estão definidos o nome e o tipo do subalgoritmo, bem como os seus parâmetros e variáveis locais; um corpo, onde se encontram as instruções (comandos) do subalgoritmo. O nome de um subalgoritmo é o nome simbólico pelo qual ele é chamado por outro algoritmo. O corpo do subalgoritmo contém as instruções que são executadas cada vez que ele é invocado. Variáveis locais são aquelas definidas dentro do próprio subalgoritmo e só podem ser utilizadas pelo mesmo. Parâmetros são canais por onde os dados são transferidos pelo algoritmo chamador a um subalgoritmo, e vice-versa. Para que possa iniciar a execução das instruções em seu corpo, um subalgoritmo às vezes precisa receber dados do algoritmo que o chamou e, ao terminar sua tarefa, o subalgoritmo deve fornecer ao algoritmo chamador os resultados da mesma. Esta comunicação bidirecional pode ser feita de dois modos que serão estudados mais à frente: por meio de variáveis globais ou por meio da passagem de parâmetros. 55 Modularização O tipo de um subalgoritmo é definido em função do número de valores que o subalgoritmo retorna ao algoritmo que o chamou. Segundo esta classificação, os algoritmos podem ser de dois tipos: funções, que retornam um, e somente um, valor ao algoritmo chamador; procedimentos, que retornam zero (nenhum) ou mais valores ao algoritmo chamador. Procedimentos Um procedimento é um subalgoritmo que executa alguma tarefa específica e não retorna valores ao algoritmo ou subalgoritmo chamador. É possível interagir com o algoritmo chamador através de variáveis globais, mas nunca explicitamente, como no caso de funções, que veremos no tópico seguinte. Portanto, a chamada de um procedimento nunca surge no meio de expressões, como no caso de funções. Pelo contrário, a chamada de procedimentos só é feita em comandos isolados dentro de um algoritmo, como as instruções de entrada (Leia) e saída (Escreva) de dados. A sintaxe da definição de um procedimento é: 1 2 3 4 5 Procedimento <nome> (<parâmetros>) Var <variáveis locais> Inicio <comandos> Fim Temos que: <nome> é o nome simbólico identificador pelo qual o procedimento é invocado por outros algoritmos; <parâmetros> são os parâmetros do procedimento; <variáveis locais> são as definições das variáveis locais ao procedimento. Sua forma é análoga à da definição de variáveis num algoritmo; <comandos> é o conjunto de instruções do corpo do procedimento, que é executado toda vez que o mesmo é invocado. O exemplo a seguir é um exemplo simples, onde um procedimento é usado para escrever o valor das componentes de um vetor. 1 2 Algoritmo Exemplo_procedimento Var vet : matriz[1..10] de real 56 Modularização 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 Procedimento ESC_VETOR() Var i : inteiro Inicio Para i de 1 até 10 faça Escreva vet[i] Fimpara Fim Procedimento LER_VETOR() Var i : inteiro Inicio Para i de 1 até 10 faça Leia vet[i] Fimpara Fim Inicio LER_VETOR() ESC_VETOR() Fim No exemplo é conveniente observar: a forma de definição dos procedimentos LER_VETOR() e ESC_VETOR(), que não possuem parâmetro, e usam a variável local i para “varrer” os componentes do vetor, lendo e escrevendo um valor por vez; e a forma de invocação dos procedimentos, por meio do seu nome, seguido de seus eventuais parâmetros (no caso, nenhum), num comando isolado dentro do algoritmo principal. Funções As funções são utilizadas para a execução de operações mediante a passagem ou não de argumentos e, sempre retornam um valor. O conceito de função é originário da ideia de função matemática (por exemplo, raiz quadrada, seno, cosseno, tangente, logaritmo, entre outras), onde um valor é calculado a partir de outro(s) fornecido(s) à função. A sintaxe da definição de uma função é dada a seguir: 1 2 3 4 5 Função <nome> (<parâmetros>) <tipo_de_dado> Var <variáveis locais> Início <comandos> Fim Temos que: 57 Modularização <nome> é o nome simbólico pelo qual a função é invocada por outros algoritmos; <parâmetros> são os parâmetros da função; <tipo de dado> é o tipo de dado da informação retornado pela função ao algoritmo chamador; <variáveis locais> consiste na definição das variáveis locais à função. Sua forma é análoga à da definição de variáveis num algoritmo; <comandos> é o conjunto de instruções do corpo da função. Dentro de um algoritmo, o comando de invocação de um subalgoritmo do tipo função sempre aparece dentro de uma expressão do mesmo tipo que o do valor retornado pela função. A invocação de uma função é feita pelo simples aparecimento do nome da mesma, seguido pelos respectivos parâmetros entre parênteses, dentro de uma expressão. A função é executada e, ao seu término, o trecho do comando que a invocou é substituído pelo valor retornado pela mesma dentro da expressão em que se encontra, e a avaliação desta prossegue normalmente. Dentro de uma função, e somente neste caso, o comando “Retorne <expressão>” é usado para retornar o valor calculado pela mesma. Ao encontrar este comando, a expressão entre parênteses é avaliada, a execução da função é terminada neste ponto e o valor da expressão é retornado ao algoritmo chamador. Vale lembrar que uma expressão pode ser uma simples constante, uma variável ou uma combinação das duas por meio de operadores. Esta expressão deve ser do mesmo tipo que o valor retornado pela função. O algoritmo a seguir é um exemplo do emprego de função para calcular o valor de um número elevado ao quadrado. 1 2 3 4 5 6 7 8 9 10 11 12 13 Algoritmo Exemplo_de_função Var X, Y : real Função Quad(w : real) : real Var Z : real Inicio Z w * w Retorne Z Fim Início Escreva "Digite um número” Leia X 58 Modularização 14 15 16 Y Quad(X) Escreva X, " elevado ao quadrado é = ", Y Fim Do exemplo anterior é importante notar que: a função “Quad” toma W como parâmetro do tipo real, retorna um valor do tipo real e possui Z como uma variável local real; o comando de invocação da função “Quad” aparece no meio de uma expressão, no comando de atribuição dentro do algoritmo principal. Exercícios: Funções 1) Faça uma função que recebe, por parâmetro, a altura e o sexo de uma pessoa e retorna o seu peso ideal. Para homens, calcular o peso ideal usando a fórmula PESO IDEAL = 72.7 * ALTURA – 58 e, para mulheres, a fórmula PESO IDEAL = 62.1 * ALTURA – 44.7. 2) Escreva uma função que recebe uma nota e verifica se é uma nota válida (de 0 a 10), retornando um valor lógico indicando se a nota é válida ou não. 3) Escreva uma função que recebe um valor inteiro e verifica se o valor é par ou ímpar. A função deve retornar um valor lógico. 4) Escreva uma função que recebe 3 notas de um aluno e uma letra. Se a letra for “A”, o procedimento deve calcular a média aritmética das notas do aluno, se a letra for “P”, deve calcular a média ponderada (pesos: 5, 3 e 2). A média calculada deve ser retornada. 5) Escreva uma função para verificar se um dado número é perfeito. 6) Escreva uma função que conte quantos algarismos possui um número inteiro. O número de algarismos deve ser retornado. 7) Escreva uma função que retorne a soma dos algarismos de um número inteiro qualquer que é passado como parâmetro. 8) Escreva uma função que recebe 3 valores reais X, Y e Z e verifique se esses valores podem ser os comprimentos dos lados de um triângulo e, neste caso, retornar qual o tipo de triângulo formado. Para que X, Y e Z formem um triângulo é necessário que a seguinte propriedade seja satisfeita: o comprimento de cada lado de um triângulo é 59 Modularização menor do que a soma do comprimento dos outros dois lados. O procedimento deve identificar o tipo de triângulo formado observando as seguintes definições: Triângulo equilátero: os comprimentos dos 3 lados são iguais; Triângulos Isósceles: os comprimentos de 2 lados são iguais; Triângulo Escaleno: os comprimentos dos 3 lados são diferentes. 9) Faça uma função que recebe a média final de um aluno e retorna o seu conceito, conforme a tabela abaixo: Nota Conceito de 0,0 a 4,9 D de 5,0 a 6,9 C de 7,0 a 8,9 B de 9,0 a 10,0 A 60 Tipos homogêneos de dados compostos 10 Tipos homogêneos de dados compostos Os tipos homogêneos são conjuntos do mesmo tipo básico. A utilização desse tipo de estrutura de dados recebe diversos nomes, tais como: variáveis indexadas, compostas, arranjos, tabelas em memória, arrays (do inglês) vetores e matrizes. Para simplificar utilizaremos somente os nomes vetores e matrizes, que serão abordados nesta unidade. Variáveis indexadas unidimensionais – Vetores Os vetores são variáveis estruturadas homogêneas capazes de armazenar uma série de informações de um mesmo tipo em uma única variável. Sua utilização é importante quando é necessário armazenar várias informações, sobre as quais, em geral, serão realizados os mesmos processamentos dentro do programa. Por exemplo, para armazenar a média dos vários alunos de uma turma na memória usando variáveis simples, seriam necessárias “n” variáveis com nomes distintos, o que torna o programa mais complexo de ser elaborado e difícil de ser entendido. Neste caso pode-se criar uma variável única que contenha todas estas informações. Os vetores são a forma mais simples de variáveis estruturadas homogêneas. São estruturas unidimensionais que armazenam um conjunto de valores de um mesmo tipo. Um vetor é na verdade, um conjunto contínuo de posições de memória identificado por um nome único. O número de elementos é estático, ou seja, o tamanho é definido uma única vez na execução do algoritmo. Um exemplo de representação de vetor pode ser visto a seguir, em que temos uma variável do tipo real, com 5 posições: altura 1.74 1.90 1.65 2.02 1.75 1 2 3 4 5 61 Tipos homogêneos de dados compostos Neste vetor, temos a representação dos valores referente à altura de cinco pessoas distintas, no qual se tem o valor 1.74 armazenado na posição 1 do vetor, até o valor 1.75 que está na posição 5 do vetor. Declaração de vetores Na declaração dos vetores devemos informar o seu nome, seu tipo (inteiro, real, caracter, ...) e seu tamanho (número de elementos). Cada elemento do vetor é identificado por um índice (unidimensional), o qual indica a sua posição no vetor. A declaração de um vetor é feita da seguinte forma: Var <nome> : vetor[<número de elementos>] de <tipo do vetor> Como exemplo de declaração temos: Var altura : vetor[5] de real A palavra reservada vetor indica que a variável “altura” será uma variável estruturada homogênea. O número 5, entre colchetes, indica a quantidade de posições do vetor. A palavra “de”, indica o tipo de informações que serão armazenadas dentro do vetor, neste caso números reais. Leitura e escrita de dados nos vetores Para fazer a leitura dos dados e a atribuição de dados num vetor, escritos num algoritmo, são necessários informar o nome do mesmo e a posição dentro do vetor na qual queremos interagir. Quando o vetor é criado, ele não possui valor inicial, podendo ser visualizado da seguinte forma: altura 1 2 3 4 5 Quando quisermos atribuir um valor diretamente a uma determinada posição do vetor, fazemos da seguinte forma: altura[1] ß 1.74 Desta forma, estamos atribuindo para a posição 1 do vetor “altura” o valor real 1.74. A representação do vetor, depois de atribuído um valor, ficaria da seguinte maneira: altura 1.74 1 2 3 4 5 62 Tipos homogêneos de dados compostos A maneira dinâmica de se atribuir um valor a uma determinada posição do vetor, é fazendo a leitura de uma valor informada pelo meio externo ao algoritmo, usando o comando “Leia”, mostrado no exemplo a seguir: Leia altura[5] Nesse exemplo, quando um valor for informado pelo usuário do algoritmo, ele será atribuído à posição 5 do vetor. Se quisermos atribuir valores a todas as posições do vetor, teríamos que usar o comando “Leia” para cada uma das posições, que ficaria assim: Leia Leia Leia Leia Leia altura[1] altura[2] altura[3] altura[4] altura[5] E se o nosso vetor tivesse 50 posições? O nosso código ficaria um tanto extenso. Entretanto, podemos utilizar uma estrutura de repetição para auxiliar nesse processo. A seguir, temos um exemplo de utilização de uma estrutura de repetição fazendo interação com um vetor: 1 2 3 4 5 6 7 8 9 Algoritmo “Leitura_vetor” Var cont : inteiro altura : real Início Para cont de 1 até 5 Passo 1 Faça Leia altura[i] Fimpara Fim Com esse algoritmo, apresentado anteriormente, temos que a estrutura de repetição “Para” usa a variável “cont” para fazer o incremento, começando em 1 e vai até 5. A variável “cont” é utilizada como índice para o vetor, e em cada interação do laço, é feita a leitura em uma posição do vetor. A maneira de fazer a leitura dos dados é bastante simples, basta referenciar o nome do vetor com a posição que desejamos. A seguir, vamos usar o comando “Escreva” para imprimir a posição 5 do vetor altura: Escreva altura[5] De mesma forma que usamos uma estrutura de repetição para fazer a atribuição de dados para as posições do vetor, podemos utilizá-la para imprimir todos os valores de um vetor. 63 Tipos homogêneos de dados compostos Um exemplo de algoritmo, que faz a leitura de um vetor com 5 posições e depois o imprime, é mostrado a seguir: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Algoritmo “leitura_escrita_vetor” Var cont : inteiro nomes : literal Início //Leitura dos valores Para cont de 1 até 5 Passo 1 Faça Escreva “Informe o nome de uma pessoa: ” Leia nomes[cont] Fimpara //Escrita dos valores Para cont de 1 até 5 Passo 1 Faça Escreva nomes[cont] Fimpara Fim Utilização de Vetores Relacionados No desenvolvimento de um algoritmo pode existir a necessidade de armazenar diferentes dados de uma determinada entidade, para isso, podemos utilizar vários vetores para armazenar tipos de dados diferentes, mas que se referem a uma mesma entidade. Por exemplo, supondo que se deseja armazenar o nome, a idade e o sexo de 50 pessoas, necessitamos criar três vetores distintos, um para os nomes, outro para as idades e, por fim, outro para os sexos, conforme código a seguir: Var nomes : vetor[100] de literal idades : vetor[100] de inteiro sexos : vetor[100] de caracter A representação pode ser vista da seguinte forma: 1 2 3 4 5 Antônio Carlos Keila Mauro Maria 1 2 3 4 5 idades 36 25 18 65 29 1 2 3 4 5 sexos M M F M F nomes ... ... 100 ... ... 100 ... ... 100 Apesar dos vetores serem armazenados na memória como três variáveis independentes, tem-se uma relação lógica através índice. A pessoa cujo nome está armazenado na posição 1 do vetor “nomes”, tem sua idade armazenada na primeira 64 Tipos homogêneos de dados compostos posição do vetor “idades” e o sexo na posição 1 do vetor “sexos”. Esta associação é facilmente implementada quando se utiliza o contador de uma estrutura de repetição como índice dos três vetores ao mesmo tempo. No código a seguir, é apresentado a implementação de um algoritmo que faz a leitura dos dados das 100 pessoas e as armazena nos vetores. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Algoritmo “vetores” Var cont : inteiro nomes : vetor[100] de literal idades : vetor[100] de inteiro sexos : vetor[100] de caracter Início Para cont de 1 até 100 faça Escreva “Digite o nome da pessoa : Leia nomes[cont] Escreva “Digite a idade da pessoa :” Leia idades[cont] Escreva “Digite o sexo da pessoa :” Leia sexos[cont] Fimpara Fim O relacionamento entre os diferentes vetores para a recuperação de informações também é feito através dos índices. Por exemplo, para imprimir o sexo e a idade de uma pessoa com nome “Carlos”, devemos inicialmente procurar o nome dele no vetor “nomes”, para saber em que posição do vetor ele se encontra. Em seguida, de posse da posição onde está armazenado o nome dele, é possível recuperar o sexo e a idade desta pessoa, já que esses dados estarão armazenados nesta mesma posição nos vetores “sexos” e “idades”. Para cont de 1 até 100 Passo 1 Faça Se nomes[cont] = “Carlos” Então Escreva “O sexo de Carlos é “, sexos[cont] Escreva “I idade de Carlos é “, idades[cont], “ anos” Interrompa Fimse Fimpara Neste código, inicialmente é buscado o nome “Carlos” no vetor de “nomes”. No momento que o algoritmo encontra o nome “Carlos”, a variável “cont” está armazenando a posição no qual se encontra no vetor nomes. Com isso, basta fazer a leitura dos vetores “sexos” e “idades” na mesma posição do vetor “nomes”, ou seja, devemos usar a variável “cont” como índice para os vetores. 65 Tipos homogêneos de dados compostos Exercícios: Vetores 10) Faça o teste de mesa para os algoritmos abaixo: a) Algoritmo 1 1 2 3 4 5 6 7 8 9 10 11 12 b) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 c) 1 2 3 4 5 6 7 8 9 10 11 12 13 Algoritmo "dez_nomes" Var nomes : vetor[10] de cadeia i : inteiro Inicio Para i de 1 até 10 faça nomes[i] ß "Joao" Fim_para Para i de 1 até 10 faça Escreva nomes[i], " na posicao ", i Fim_para Fim Algoritmo 2 Algoritmo "vetor2" Var t : vetor[10] de inteiro i, n : inteiro Início Escreva "Digite um numero: " Leia n Para i de 1 até 10 faça t[i] ß i * n Fim_para Para i de 1 até 10 faça Escreva i ," X ", n , " = " , t[i] Fim_para Fim Algoritmo 3 Algoritmo "varias_notas" Var notas : vetor[5] de real cont : inteiro Início Para cont de 1 até 5 faça Escreva "Digite a nota do aluno ", cont Leia notas[cont] Fim_para Para cont de 1 até 5 faça Escreva "o aluno " , cont , " tirou nota " , notas[cont] Fim_para Fim 11) Escreva uma função que recebe um vetor de inteiros de qualquer tamanho e retorne a quantidade de números pares positivos contidos no vetor. 12) Faça uma função que verifique a existência de um determinado valor em um vetor de inteiros. Se encontrar retorna a posição, senão retorna -1. 13) Faça um algoritmo que leia um vetor de 500 posições de números inteiros e divida todos os seus elementos pelo maior valor contido no vetor. Mostre o vetor após os cálculos. Sugestão: escreva uma função que encontre o maior valor do vetor. 66 Tipos homogêneos de dados compostos 14) Dados 3 vetores (A, B e C) com as mesmas dimensões (tamanho), faça um programa que some os vetores A e B e armazene o vetor resultante em C. 15) Escreva um algoritmo que leia dois vetores de 50 posições e faça a multiplicação dos elementos de mesmo índice, colocando o resultado em um terceiro vetor. Mostre o vetor resultante. 16) Escreva um algoritmo que leia 2 vetores X(10) e Y(10). Crie, a seguir, um vetor P, que seja: a) A união de X e Y b) A interseção entre X e Y c) A intercalação de X e Y Escreva um vetor P para cada operação. 17) Escreva uma função que recebe um vetor de 20 números inteiros, por parâmetro, e retorna a soma dos elementos do vetor. 18) Escreva um algoritmo que ordene um vetor de 50 posições em ordem crescente usando o método bolha (buble sort). 19) Escreva um algoritmo que lê um vetor N(20) e o escreve. Troque, a seguir, o primeiro elemento com o último, o segundo com o penúltimo, e assim por diante, até o décimo com o décimo primeiro e escreva o veto N modificado. 20) Escreva um algoritmo que inverta o conteúdo de dois vetores A e B de 50 posições, conforme ilustrado a seguir: A 5 6 8 2 3 B 1 7 9 0 4 Após a inversão A 4 0 9 7 1 B 3 2 8 6 5 21) Implementar um algoritmo que calcule e escreva o somatório dos valores armazenados numa variável unidimensional A de 100 elementos numéricos. Exemplo: A 32 1 17 10.7 ... 15.8 2 3 ... 100 Somatório = 32 + 17 + 10.7 + ... + 15.8 = 75.5 = ∑ 22) Escreva um algoritmo que lê um vetor L(5) que fornece os 5 números sorteados em algum sorteio da LOTO. Leia, a seguir, um número não determinado de vetores J(6) cada um contendo na primeira posição o número de identificação do cartão e nas demais posições as opções do apostador em questão. Para cada apostador escrever o 67 Tipos homogêneos de dados compostos número de seu cartão e o seu número de acertos, assinalando com uma mensagem quando tiver 3, 4 ou 5 acertos. Variáveis indexadas bidimensionais – Matrizes Assim como os vetores, as matrizes são estruturas de dados homogêneas (armazenam informações de um único tipo). A diferença entre estas duas estruturas está no fato de que os vetores são estruturas unidimensionais e as matrizes são bidimensionais. Em um vetor, para acessar um valor qualquer, é necessário usar um índice para determinar sua posição. Na matriz dois índices são necessários. O primeiro determina em que linha da matriz se encontra o elemento, enquanto o segundo determina a coluna. A seguir é apresentado um exemplo de uma matriz para armazenar as quatro notas de uma turma de trinta alunos: 1 2 3 .. .. .. .. 30 1 2 3 4 7.5 6.0 9.5 .. .. .. .. 4.0 8.0 7.0 9.2 .. .. .. .. 5.8 7.0 5.5 10.0 .. .. .. .. 7.0 9.0 8.0 8.7 .. .. .. .. 6.5 A forma que os dados são dispostos na matriz deve ser definida pelo programador. Neste caso optou-se por criar quatro colunas onde cada coluna apresenta as notas de uma avaliação (Por exemplo, prova 1, prova 2, prova 3 e prova 4 respectivamente) e em cada linha estão representadas as notas de um aluno (Na linha 1, estão as quatro notas do primeiro aluno e assim por diante). A célula formada pelo cruzamento da linha “i” com a coluna “j” armazena a nota do aluno “i” na prova “j”. Por exemplo, para imprimir a nota do aluno 3 na prova 2 deve ser mostrado o valor armazenado na terceira linha e na segunda coluna da matriz, neste caso 9,2. 1 2 3 4 68 Tipos homogêneos de dados compostos 1 2 3 .. .. .. .. 30 7.5 6.0 9.5 .. .. .. .. 4.0 8.0 7.0 9.2 .. .. .. .. 5.8 7.0 5.5 10.0 .. .. .. .. 7.0 9.0 8.0 8.7 .. .. .. .. 6.5 Declaração e Utilização de Matrizes A declaração e a forma de utilização de matrizes são semelhantes à de vetores, exceto pelo fato de que dois índices devem ser definidos neste caso, enquanto apenas um índice era suficiente para os vetores. Estes índices representam o número de linhas e de colunas da matriz. A declaração de um vetor é feita da seguinte forma: Var <nome> : matriz[<número de linhas>][<número de colunas>] de <tipo do matriz> Na sequencia é mostrado um exemplo de declaração de uma matriz de números reais composta de 5 linhas e 10 colunas: Var notas : matriz[5][10] de real Exercícios: Matrizes 1) Escreva um algoritmo que lê uma matriz M(6,6) e um valor A, em seguida faça a multiplicação da matriz M pelo valor de A. 2) Escreva um algoritmo que lê 3 matrizes M(4,6), N(4,6) e O(6,4), gerando uma matriz que seja: a. a soma de M com N b. a diferença de M com N c. o produto de N por O Escrever as matrizes calculadas. 3) Faça um algoritmo que leia uma matriz de 50x50 de números reais. A seguir, multiplique cada linha pelo elemento da diagonal principal daquela linha. Mostre a matriz após as multiplicações. 69 Tipos homogêneos de dados compostos 4) Faça um algoritmo que gere uma matriz com o seguinte conteúdo: 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 1 2 2 2 2 1 0 0 1 2 3 3 2 1 0 0 1 2 3 3 2 1 0 0 1 2 2 2 2 1 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 5) Escreva um algoritmo que leia um número inteiro A e uma matriz 30x30 de inteiros. A seguir, crie uma função que retorne a quantidade de valores iguais a A que estão na matriz. 6) Faça um algoritmo que leia uma matriz 20x20 de reais e some cada uma das linhas, armazenando o resultado da soma em um vetor. A seguir, multiplique cada elemento pela soma da sua linha. Mostre a matriz resultante. 7) Considere uma matriz 8x8 de números inteiros representando um tabuleiro de xadrez. Assuma inicialmente que as peças já estão dispostas no tabuleiro e que as mesmas são identificadas conforme a tabela abaixo: Peça Peão Cavalo Bispo Torre Rainha Rei Posição vazia Branca 1 2 3 5 11 50 0 Preta -1 -2 -3 -5 -11 -50 0 5 1 0 0 0 0 -1 -5 3 1 0 0 0 0 -1 -3 2 1 0 0 0 0 -1 -2 11 50 1 1 0 0 0 0 0 0 0 0 -1 -1 -50 -11 2 1 0 0 0 0 -1 -2 3 1 0 0 0 0 -1 -3 5 1 0 0 0 0 -1 -5 a) Escreva um algoritmo que o usuário possa informar a posição atual da torre e sua nova posição no tabuleiro, e o algoritmo verifica se o movimento é válido, isto é, se a movimentação da torre para a nova posição não viola as regras do jogo. Verifique também se a posição informada pelo usuário realmente contém uma torre. b) Idem para a peça bispo. c) Escreva um algoritmo para indicar o jogador que está vencendo (quantitativamente). Considerações: A torre movimenta-se somente no sentido horizontal e vertical. O bispo movimenta-se somente na diagonal. A peça movimentada não pode passar sobre outra peça do mesmo jogador. 70 Tipos heterogêneos de dados compostos 11 Tipos heterogêneos de dados compostos Existem quatro tipos de dados primitivos que o computador manipula, sendo que já conhecemos e utilizamos, são eles: os reais, os inteiros, os literais e os lógicos. Com eles podemos definir novos tipos que possibilitam agrupar um conjunto de dados homogêneos (mesmo tipo) sob um único nome (a exemplo dos vetores e matrizes), ou de tipos heterogêneos (tipos diferentes). Esse tipo de dados heterogêneos é conhecido como registro. Registros são conjuntos de dados logicamente relacionados, mas de tipos diferentes. As matrizes são tipos de variáveis que agrupam dados similares, enquanto que os registros agrupam, geralmente, dados desiguais. Aos itens de dados de um registro dá-se o nome de “membros” ou “componentes”, enquanto que aos itens de uma matriz (ou vetor) dá-se o nome de “elementos”. Registros É uma estrutura composta por um conjunto de variáveis de tipos diferentes, primitivos e/ou construídos, logicamente relacionados que podem ser referenciados por um mesmo nome (identificador do tipo registro) ou individualmente. Este tipo de estrutura é utilizada para relacionar dados pertencentes a um mesmo objeto. Ex: fichário de um funcionário. Sintaxe para criação de um registro: 1 2 3 Registro = <nome_do_registro> <componentes_do_registro> Fim_registro Temos que: 71 Tipos heterogêneos de dados compostos <nome_do_registro> é um nome escolhido pelo programador e será considerado como um novo tipo de dados, como os tipos básicos; <componentes_do_registro> é o local onde o programador definirá as variáveis desse novo tipo, se valendo de outros tipos já definidos. A definição de um registro deve figurar no cabeçalho do algoritmo (ou subalgoritmo) antes da declaração das variáveis relativas a ele. Um registro pode ser definido em função de outros registros já definidos. Exemplo 1, registro para armazenamento de data: 1 2 3 4 5 Registro = Data dia : inteiro mês : literal[10] ano : inteiro Fim_registro Exemplo 2, registro para armazenamento de dados do aluno: 1 2 3 4 Registro = Aluno matricula : inteiro nota[3], media : real Fim_registro Exemplo 3, dados cadastrais: 1 2 3 4 5 6 Registro = Dados nome : literal[40] idade : inteiro sexo : caracter salario : real Fim_registro Atribuição A atribuição de valores a um registro segue o mesmo padrão de atribuição em uma variável de tipo de dado primitivo, mas com o diferencial que devemos especificar o nome do registro e o nome do campo contido no registro, separados por um ponto. Sintaxe: <nome do registro>.<nome campo> valor Exemplo de um algoritmo que faz a atribuição de valores para uma estrutura que armazena data: 6 7 8 9 10 11 Algoritmo “Exemplo de atribuição” Registro dia : mês : ano : = Data inteiro inteiro inteiro 72 Tipos heterogêneos de dados compostos 12 13 14 15 16 17 18 19 20 Fim_registro Var nascimento_joao : Data Início nascimento_joao.dia 25 nascimento_joao.mes 5 nascimento_joao.ano 1965 Fim Leitura e escrita Para fazer a leitura e escrita de um registro, devemos seguir a mesma ideia de atribuição de valores ao registro, devendo fazer a leitura e/ou escrita individual de cada um dos campos contidos no registro. Sintaxe para leitura: Leia <nome_do_registro>.<nome_do_campo>; Sintaxe para escrita Escreva <nome_do_registro>.<nome_do_campo>; Exemplo Neste exemplo, é mostrado um algoritmo que utiliza um vetor, para armazenar dados de 10 funcionários. Nome: Fone: Salário: Idade: Nome: Fone: Salário: Idade: 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Nome: Fone: Salário: Idade: 2 Nome: Fone: Salário: Idade: 3 Nome: Fone: Salário: Idade: ... Algoritmo “Dados cadastrais de funcionários” Registro = Funcionario NOME[15], FONE[10] : literal SALARIO : real IDADE : inteiro Fim_egistro; Var VFUNC : vetor[10] de Funcionario //vetor de registros do tipo //funcionário, com 10 posições CONT : inteiro Procedimento CADASTRAR() Procedimento MOSTRAR() 10 73 Tipos heterogêneos de dados compostos 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Início OP : inteiro OP 1 CONT 1 Enquanto OP <> 3 faça Escreva “1 - Cadastrar” Escreva “2 - Consulta” Escreva “3 - Sair” Leia OP Selecione OP Caso 1 : CADASTRAR() Caso 2 : MOSTRAR() Caso 3 : Escreva “FIM!” Senão : Escreva “Opção inválida” Fim_selecione Fim_enquanto Fim Procedimento CADASTRAR() Início Enquanto CONT <= 100 faça Escreva “Informe nome do funcionário: ” Leia VFUNC[CONT].NOME Escreva “Informe telefone do funcionário: ” Leia VFUNC[CONT].FONE Escreva “Informe salário do funcionário”: ” Leia VFUNC[CONT].SALARIO Escreva “Informe idade do funcionário: ” Leia VFUNC[CONT].IDADE CONT CONT+1 Fim_enquanto Se CONT > 100 então Escreva “Vetor completo!” Fim_se Fim Procedimento MOSTRAR() Var CONT1 : inteiro Início CONT1 1 Se CONT <= 1 então Escreva “Não existem elementos cadastrados!” Senão Enquanto CONT1 <= 100 faça Escreva “Nome do funcionário ”, CONT1, “:”, VFUNC[CONT1].NOME Escreva “Telefone do funcionário ”, CONT1, “:”, VFUNC[CONT1].FONE Escreva “Salário do funcionário ”, CONT1, “:”, VFUNC[CONT1].SALARIO Escreva “Idade do funcionário”, CONT1, “:”, VFUNC[CONT1].IDADE Fim_enquanto Fim_se Fim Exercícios 4) Para cada uma das situações a seguir crie um tipo de dados registro e faça um algoritmo para armazenar o que se pede na quantidade que se pede: a. Um apicultor necessita armazenar os dados de 100 colmeias, que são: código, 74 Tipos heterogêneos de dados compostos b. 5) região, estado, qualicação (forte, médio, fraco), número de abelhas; Um comerciante deseja armazenar os dados de 50 produtos, que são: código, descrição, quantidade em estoque, quantidade mínima e preço. Faça um algoritmo que crie os tipos com os campos abaixo e depois leia todas as informações de 40 registros em um vetor de registros. Depois de ler, buscar e mostrar uma listagem de todos os funcionários(as) cujo SALÁRIO seja maior que R$ 500,00, o Estado Civil igual CASADO(A) e que reside no estado de SP. Registro: Cadastro Nome Identidade Salário Endereço CPF Estado Civil Idade Sexo Registro: Endereço Rua Número Complemento Cidade Estado 6) Uma pessoa cadastrou um conjunto de 15 registros contendo o nome da loja, telefone e preço de um eletrodoméstico. Desenvolver um algoritmo que permita exibir qual foi a média dos preços cadastrados e uma relação contendo o nome e o telefone das lojas cujo preço estava abaixo da média. 7) Um provedor de acesso à Internet mantém o seguinte cadastro de clientes em fichas de papel: Código; Nome; E-mail; MegaBytes utilizados; Se possui página pessoal onde armazena-se o caractere S-sim ou N-não. Elabore um algoritmo que leia as informações digitadas pelo usuário e em seguida calcule e mostre um relatório contendo o valor a ser pago por cada cliente. Considere que os primeiros 200 MB tem um custo de R$95,00 e as MB excedentes tem o custo de R$2,50 por MB. Para os clientes que têm página pessoal adicionar R$40,00 ao total. Imagine que o provedor de acesso tem no máximo 5000 clientes. Pergunte ao usuário qual a quantidade correta de clientes antes de iniciar as leituras e cálculos. Caso ele tenha mais de 5000 clientes, envie uma mensagem pedindo para que ele entre em contato com o suporte técnico. 8) Uma determinada biblioteca possui obras de ciências exatas, humanas e biológicas, totalizando 1500 volumes, distribuídos em cada uma das áreas. O proprietário resolveu agrupar as informações de cada livro no seguinte registro: Código de catalogação que contém um valor numérico Doação (S/N) 75 Tipos heterogêneos de dados compostos Nome da obra Nome do autor Editora Área Palavras-chaves para localização do livro Construir um algoritmo que faça os seguintes passos: a. Leia todos as informações dos 1500 volumes e considere que o usuário poderá inserir os livros em qualquer ordem de áreas ou código de catalogação; b. Use o método da bolha para ordenar os livros, usando o código de catalogação como chave de ordenação; c. Mostre quantos livros existem de cada área existem na biblioteca; d. Permita ao usuário consultar diversas vezes as informações que foram cadastradas. Ele pode fazer a consulta por código catalogação ou por palavra chave ou também pode sair. Pergunte ao usuário o que ele deseja fazer. Depois que ele escolher, peça que ele digite um código de catalogação ou uma palavra chave, dependendo da escolha realizou. Procure nos campos referentes ao tipo de pesquisa. Encontrando livros que atendam ao que o usuário pediu, todas as informações do livro deverão ser exibidas. Caso não encontre nenhum livro, deve-se exibir uma mensagem de aviso ao usuário que não existe livro com aquela palavra chave ou código. 9) Suponha que você esteja realizando uma pesquisa e precise obter os seguintes dados de um conjunto de 1000 pessoas. NOME; SEXO; COR DOS OLHOS; ALTURA; PESO ; DATA DE NASCIMENTO; O campo SEXO apresenta o valor 1 quando indica sexo masculino e o valor 0 quando representa as mulheres. Crie um algoritmo que realize a leitura desses dados e imprima duas listagens. 10) Faça um algoritmo que, utilizando registros, leia o nome e data de nascimento (dia, mês, ano) de 40 pessoas, calcule e mostre a idade de cada pessoa e o nome da pessoa mais velha. Suponha que não temos duas (ou mais) pessoas com a mesma idade. 11) Uma companhia resolveu facilitar a sua folha de pagamentos. Para tal, mandou criar uma listagem de todos os funcionários que recebam mais de 30 salários mínimos. Escreva um algoritmo para criar a listagem pedida, sabendo que os registros possuem os seguintes campos: NOME DO FUNCIONÁRIO CARGO SALÁRIO 76 Tipos heterogêneos de dados compostos 12) Uma indústria faz a folha mensal de pagamentos de seus 80 empregados baseado numa listagem em papel com os dados de cada funcionário, os quais são: matrícula nome salário bruto Escreva um programa que permita ao usuário ler os dados dessa listagem e depois de processar os dados dessa tabela e emitir, para cada funcionário, seu contracheque, no seguinte formato: MATRÍCULA: NOME: SALÁRIO BRUTO: DEDUÇÃO INSS: SALÁRIO LÍQUIDO: Informações adicionais: O desconto do INSS é de 11% do salário bruto; O salário líquido é a diferença entre o salário bruto e a dedução do INSS. 13) Em uma biblioteca deseja-se implantar um sistema informatizado de busca de livros e teses. As teses possuem os seguintes campos: Título do Trabalho; Nome do Autor; Universidade; Orientador; Ano; Cidade; 3 palavras chaves utilizadas para busca. Os livros possuem os seguintes campos: Autor; Editora; Título; Ano; ISBN; 3 palavras chaves utilizadas para busca. A partir dessas informações faça um algoritmo que Crie tipos de registro para armazenar os dados das teses e dos livros; Implemente um cadastro para livros e teses, permitindo armazenar 30 teses e 140 livros e uma forma de realizar a leitura destes livros e teses. Depois de cadastrar disponibilize as seguintes opções para o usuário: a. Permita ao usuário buscar as teses que possuem uma palavra-chave digitada por ele; b. Buscar todos os livros de um determinado autor escolhido pelo usuário; c. Buscar as teses de um determinado Ano; d. Sair do Sistema. 77 Tipos heterogêneos de dados compostos 14) Um restaurante possui mesas organizadas em 15 filas de 10 mesas e mantêm por mesa, com as seguintes informações: Mesa disponível Cliente Quantidade de itens pedidos Lista de itens pedidos Total parcial % de gorjeta Total da nota A lista de itens pedidos é definida pelos campos Código do item pedido Descrição do item pedido Quantidade do item pedido Valor unitário do item pedido Valor total do item pedido A quantidade máxima de itens pedidos em uma ficha é de 1000 itens. Os itens pedidos são bebidas (refrigerantes, cervejas, vinhos, etc), alimentos (batata frita, porção de calabresa, etc), dentre outros. O restaurante também possui uma lista de 100 itens que devem ser armazenados em um vetor chamado ItensRestaurante. Este vetor de registro é tipo Item, o qual possui a seguinte declaração: Registro = Item Inicio codigo: inteiro descricao: literal preco: real Fim Com base nessas informações faça um algoritmo que permita ao usuário utilizar as seguintes opções: a. Iniciar todas as mesas: Nessa opção todas as mesas terão suas quantidades de pedidos zeradas e tornará a mesa disponível para uso. b. Alterar o valor de um item: Nessa opção será possível alterar o preço de um item digitando-se o código do item que se deseja alterar e o novo preço. O programa deve mostrar o preço antigo e o novo preço. c. Iniciar uma mesa: Nessa opção será utilizada quando uma ou mais pessoas solicitarem uma mesa, o sistema procura a primeira mesa disponível. Assim que encontrar a passará para indisponível e informará ao(s) cliente(s) o número da mesa (imprimindo este número). Depois disso, o(s) cliente(s) indicarão se desejam colocar o nome de um deles na nota. Se precisar(em) deve-se ler este nome e incluir na ficha da mesa. Senão, por padrão inclui-se o nome "Consumidor". O cliente também fará a opção de pagar ou não gorjeta (a cota de gorjeta é de 10% do total parcial). Estas informações também irão para a ficha da mesa. d. Incluir um pedido na ficha: O garçom irá entregar um papel com as seguintes informações: o código da mesa, o código do item e a quantidade deste item. As informações de descrição e preço unitário serão buscadas no vetor de itens e incluídas na ficha da mesa. 78 Tipos heterogêneos de dados compostos e. f. Fechar uma mesa: Quando o cliente pedir a conta para fechar a mesa, ele irá até o caixa e informará o número da mesa que estava, os itens serão totalizados e apresentado da seguinte forma: Depois de imprimir estas informações o algoritmo deverá tornar a mesa disponível para outros clientes e zerar as informações da mesa. Sair do programa: Finaliza o programa. 79