Baixe o app para aproveitar ainda mais
Prévia do material em texto
Apontamentos de Me´todos de Programac¸a˜o I Marta Pascoal Departamento de Matema´tica, Universidade de Coimbra 2014 Conteu´do 1 Noc¸o˜es gerais 3 1.1 Introduc¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.2 Estrutura e funcionamento ba´sicos dum computador digital . . . . . . . . . . . . . . . 5 1.3 Representac¸a˜o de informac¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.3.1 Representac¸a˜o de inteiros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.3.2 Representac¸a˜o de reais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 1.3.3 Representac¸a˜o de caracteres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 1.4 Metodologia da Programac¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.4.1 Construc¸a˜o de um programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.5 Exerc´ıcios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2 Conceitos fundamentais de programac¸a˜o imperativa 11 2.1 Introduc¸a˜o a` linguagem Pascal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.1.1 Exerc´ıcios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.2 Tipos de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.2.1 Tipos elementares de dados pre´-definidos . . . . . . . . . . . . . . . . . . . . . 16 2.2.2 Tipos definidos pelo utilizador . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.3 Declarac¸a˜o de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 2.3.1 Varia´veis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 2.3.2 Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 2.4 Expresso˜es aritme´ticas e lo´gicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.4.1 Exerc´ıcios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.5 Instruc¸o˜es . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.5.1 Instruc¸a˜o de atribuic¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.5.2 Instruc¸a˜o de sequenciac¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.5.3 Instruc¸o˜es de entrada/sa´ıda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 2.5.4 Exerc´ıcios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.6 Estruturas de controlo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 2.6.1 Instruc¸o˜es de selecc¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 2.6.2 Exerc´ıcios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 2.6.3 Instruc¸o˜es de repetic¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 2.6.4 Exerc´ıcios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 2.7 Tabelas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 2.7.1 Exerc´ıcios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 1 3 Metodologia da programac¸a˜o 59 3.1 Subprogramas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 3.1.1 Func¸o˜es . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 3.1.2 Subprogramas e domı´nio de identificadores . . . . . . . . . . . . . . . . . . . . 61 3.1.3 Procedimentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 3.1.4 Paraˆmetros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 3.1.5 Exerc´ıcios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 3.2 Tabelas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 3.2.1 Operac¸o˜es com vectores ordenados (ordem crescente) . . . . . . . . . . . . . . . 79 3.2.2 Exerc´ıcios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 3.3 Recursividade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 3.3.1 Exerc´ıcios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 4 Registos e conjuntos 102 4.1 Registos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 4.2 Conjuntos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 4.3 Exerc´ıcios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 Bibliografia 114 2 Cap´ıtulo 1 Noc¸o˜es gerais 1.1 Introduc¸a˜o Um computador e´ uma ferramenta que permite executar tarefas de forma mais eficiente, ra´pida e precisa do que manualmente. Programac¸a˜o de computador pode ser definida como o processo de planificar uma sequeˆncia de instruc¸o˜es para um computador seguir, e com a qual pretendemos resolver problemas. A resoluc¸a˜o de um problema utilizando computadores e programac¸a˜o e´ constitu´ıda por uma fase de resoluc¸a˜o e uma fase de implementac¸a˜o. Durante a fase de resoluc¸a˜o e´ necessa´rio • analisar, compreender e definir claramente o problema; • descrever uma soluc¸a˜o geral, isto e´, uma sequeˆncia de passos que possam ser usados para resolver o problema (atrave´s de um algoritmo, isto e´, uma sequeˆncia de passos para resolver o problema em tempo finito); • seguir os passos indicados e verificar se o me´todo encontrado resolve realmente o problema. A fase de implementac¸a˜o passa por • traduzir o algoritmo num co´digo (ou seja, numa linguagem de programac¸a˜o); • garantir que o computador segue as instruc¸o˜es e verificar a correcc¸a˜o das respostas dadas; • e utilizar efectivamente o programa. Uma linguagem de programac¸a˜o (neste curso estudaremos a linguagem Pascal) e´ um conjunto de regras, s´ımbolos e palavras especiais, utilizadas para construir um programa, com base num algo- ritmo, suficientemente “simples” para poderem ser entendidas por um computador. As linguagens de programac¸a˜o dividem-se em linguagens • de baixo n´ıvel, como a linguagem ma´quina (composta de instruc¸o˜es codificadas em bina´rio), ou a linguagem assembly (que usa mnemo´nicas para representar instruc¸o˜es de linguagem ma´quina para um computador particular); e • de alto n´ıvel, como o Fortran, o Pascal ou o C (que sa˜o mais pro´ximas dos conceitos humanos e independentes do processador). A escrita do texto de um programa deve ser documentada, isto e´, deve ser cuidada e acompanhada de comenta´rios que o tornem mais fa´cil de compreender e modificar por outros. Apo´s conclusa˜o deste 3 processo tem lugar a manutenc¸a˜o do programa, ou seja, a sua modificac¸a˜o por forma a incluir outras melhorias ou a corrigir erros. Mostramos agora exemplos de alguns programas escritos em linguagem Pascal. 1. program exemplo1(output); begin writeln(’ola’) end. 2. program exemplo2(input, output); var x, y: integer; begin readln(x); readln(y); writeln(x+y) end. 3. program exemplo3(input, output); var x, y: integer; begin writeln(’x?’); readln(x); writeln(’y?’); readln(y); writeln(x, ’+’, y, ’=’, x+y) end. 4. program exemplo4(input, output); var x, y: integer; begin writeln(’x?’); readln(x); if x < 0 then y := -x else y := x; writeln(’O valor absoluto de ’, x, ’e’, y) end. 5. program exemplo5(input, output); var i, n: integer; aux: real; begin aux := 0; writeln(’n?’); readln(n); for i:=1 to n do aux := aux + 1/sqr(i); writeln(’Resultado: ’, aux)end. 4 1.2 Estrutura e funcionamento ba´sicos dum computador di- gital O modelo de Von-Neumann, na figura seguinte, representa de forma simples a organizac¸a˜o interna de um computador. Unidade central de processamento Dispositivo de Unidade aritme´tica e lo´gica Dispositivo de entrada Unidade de controlo sa´ıda Memo´ria central Neste modelo um computador digital tem treˆs unidades principais, • a unidade central de processamento (CPU): que executa operac¸o˜es aritme´ticas e lo´gicas ele- mentares estipuladas pelo programa e efectua controlo do sistema. Esta divide-se, por sua vez, em: – unidade aritme´tica e lo´gica, e – unidade de controlo; • as unidades de entrada e sa´ıda: responsa´veis pela comunicac¸a˜o com o exterior; • e a memo´ria central: onde sa˜o armazenados programas, dados e resultados. Chamamos de hardware as componentes f´ısicas de um computador (que sa˜o fixas) e de software o conjunto de programas dispon´ıveis num computador (que e´ manipula´vel). 1.3 Representac¸a˜o de informac¸a˜o A informac¸a˜o pode ser representada de forma analo´gica (com variac¸a˜o cont´ınua), ou de forma digital (com variac¸a˜o discreta). Os computadores actuais sa˜o sistemas de informac¸a˜o digital, ja´ que a variac¸a˜o e´ discreta (e finita). A informac¸a˜o que usam e´ a informac¸a˜o digital bina´ria, cuja unidade elementar e´ o bit (binary information digit). Este d´ıgito pode representar os estados 0/1, verdadeiro ou falso. Para representar mais informac¸a˜o e´ necessa´rio juntar va´rios bits por forma a obter outros estados distintos. A memo´ria de um computador e´ uma sequeˆncia de ce´lulas que permitem o armazenamento de uma palavra; a palavra e´ uma sequeˆncia de um nu´mero fixo de bits que formam uma unidade manipula´vel. A memo´ria dum computador e´ definida pelo nu´mero de palavras que consegue armazenar. Assim, temos: 23 bits = 1 byte 220 bytes = 1024 Kb = 1 M 210 bytes = 1 Kb 230 bytes = 1024 M = 1 G Cada palavra em memo´ria tem um enderec¸o u´nico, por forma a permitir o acesso a essa informac¸a˜o. 1.3.1 Representac¸a˜o de inteiros Qualquer nu´mero natural pode ser representado em notac¸a˜o bina´ria. Assim, dado natural n ∈ IN existem k ∈ IN e bi ∈ {0, 1}, i = 1, . . . , k, tais que n = k∑ i=0 bi2 i Por exemplo, 5 710 = 1× 22 + 1× 21 + 1× 20 72 = 00000111 e 1610 = 1× 24 + 0× 23 + 0× 22 + 0× 21 + 0× 20 162 = 00010000 Para representar o sinal de um inteiro pode usar-se o primeiro bit. Neste caso a representac¸a˜o e as operac¸o˜es com estes valores sa˜o exactas. Contudo, se a capacidade de armazenamento e´ ultrapassada ocorre um erro de overflow . 1.3.2 Representac¸a˜o de reais Em representac¸a˜o v´ırgula flutuante um real x e´ escrito como m×Be, com − E < e < E e −M < m < M onde m e´ a mantissa, B e´ a base, e e´ o expoente, com Sinal expoente mantissa 1 bit 8 bits 23 bits Considerando B = 10, podemos escrever 23.48 = 0.2348× 102 e −0.02348 = −0.2348× 10−1 Tanto o expoente como a mantissa podem ser representados em notac¸a˜o bina´ria. Neste caso a gama de variac¸a˜o de valores reais representados num computador e´ finita e a variac¸a˜o na˜o e´ cont´ınua. Em consequeˆncia a representac¸a˜o e as operac¸o˜es na˜o sa˜o exactas. 1.3.3 Representac¸a˜o de caracteres Cada cara´cter e´ taduzido por um inteiro, de acordo com a tabela ASCII (American Standard Code for Information Interchange), que por sua vez e´ representado por um co´digo de 8 bits: 00 16 32 48 64 80 96 112 0 NUL DLE 0 @ P ‘ p 1 SOH DC1 ! 1 A Q a q 2 STX DC2 " 2 B R b r 3 ETX DC3 # 3 C S c s 4 EOT DC4 $ 4 D T d t 5 ENQ NAK % 5 E U e u 6 ACK SYN & 6 F V f v 7 BEL ETB ’ 7 G W g w 8 BS CAN ( 8 H X h x 9 HT EM ) 9 I Y i y 10 LF SUB * : J Z j z 11 VT ESC + ; K [ k { 6 12 FF FS , < L \ l | 13 CR GS - = M ] m } 14 SO RS . > N ^ n ~ 15 SI US / ? O _ o DEL 1.4 Metodologia da Programac¸a˜o 1.4.1 Construc¸a˜o de um programa Para que o computador entenda os comandos de um programa escrito numa linguagem de alto n´ıvel e´ necessa´rio transformar o programa escrito pelo programador noutro, que possa ser compreendido pela CPU, isto e´, em linguagem ma´quina. Para esse efeito, existe software de suporte, que “traduz” o programa de alto n´ıvel - dito programa fonte – no seu equivalente em linguagem ma´quina, o programa objecto. A esse software, da´-se o nome de compilador. Podemos, portanto, definir treˆs fases para conseguir implementar um programa num computador e poder executa´-lo, isto e´, poˆr o programa em funcionamento efectivo: • Fase de elaborac¸a˜o do programa: construc¸a˜o do programa para executar uma dada tarefa. Esta fase deve passar ela pro´pria por va´rias etapas: – Identificac¸a˜o do problema que se pretende resolver. – Especificac¸a˜o dos dados necessa´rios, do resultados pretendidos e da relac¸a˜o entre ambos. – Definic¸a˜o do algoritmo, o que deve passar pela escrita de um pseudo-co´digo duma sequeˆncia de instruc¸o˜es que definem um me´todo de resoluc¸a˜o do problema. – Primeira versa˜o do programa. – Simulac¸a˜o do programa para alguns valores, de modo a evitar eventuais erros de execuc¸a˜o. Consequentes correcc¸o˜es ou aperfeic¸oamentos. – Compilac¸a˜o e executac¸a˜o, e possivelmente novas correcc¸o˜es ou aperfeic¸oamentos. • Fase de compilac¸a˜o: traduc¸a˜o de um programa fonte num programa objecto. Podem ocorrer, nesta fase, erros le´xicos ou sinta´cticos, como por exemplo, no caso de se ter cometido um erro ortogra´fico, ou usado incorrectamente uma dada construc¸a˜o (instruc¸o˜es incompletas ou incompat´ıveis). Nesta situac¸a˜o o compilador termina a sua tarefa com mensagens de erro, erros de compilac¸a˜o, e identificac¸a˜o dos erros ou da zona a partir da qual deixou de entender o fluxo de instruc¸o˜es. Caso os erros na˜o tenham sido suficientemente graves para interromper a traduc¸a˜o, o programa objecto e´ gerado de qualquer modo, sendo as mensagens enviadas pelo computador simples avisos (que devemos ter em conta e corrigir). Noutros casos, o compilador na˜o consegue “recuperar” os erros e na˜o gera co´digo ma´quina, ou seja, na˜o gera o programa objecto. O programador e´ obrigado a corrigir os erros. • Fase de execuc¸a˜o: funcionamento do programa (objecto). Tambe´m nesta fase podem ocorrer erros, ditos erros de execuc¸a˜o: por introduc¸a˜o incorrecta de dados, erros semaˆnticos, algoritmo mal constru´ıdo ou inadequado. Estes erros podem ser detectados de dois modos: o programa aborta, isto e´, termina repentinamente (por vezes sem enviar qualquer mensagem intelig´ıvel) ou enta˜o devolve resultados errados ou demasiado estranhos. Cabe ao programador a identificac¸a˜o da situac¸a˜o de erro e a sua correcc¸a˜o. 7 Fase de compilac¸a˜o: Programa fonte −→ Compilador Erros de com- pilac¸a˜o Programa ob- jecto Fase de execuc¸a˜o: Dados −→ Execuc¸a˜o do programa Erros de execuc¸a˜o Resultados Um algoritmo e´ uma sequeˆncia finita e ordenada de instruc¸o˜es (escritas numa linguagem natu- ral) e que permite resolver um dado problema. Um programa e´ uma sequeˆncia finita de instruc¸o˜es, bem definidas e sem ambiguidades, que podem ser executadas mecanicamente, em tempo finito, e utilizando quantidades finitas de recursos. Um computador e´ gerido por programas, e podemos criar novos programas de que necessitemos. Para uma efectiva e eficiente construc¸a˜o de programas, sa˜o necessa´rios: um bom algoritmo, ordem e me´todo. Pretendemos agora sumariar alguns princ´ıpios fundamentais que servem como base para conseguir um bom programa, o mais rapidamente poss´ıvel. Estes princ´ıpios sa˜o especialmente importantes quanto mais complexa e´ a tarefa em causa. A apre- sentac¸a˜o seguinte salienta a necessidade de uma programac¸a˜o estruturada.Assim, a metodologia da programac¸a˜o tem como objectivos principais a atingir os seguintes: • Correcc¸a˜o: O programa deve obedecer a`s especificac¸o˜es, para poder resolver o problema pro- posto. O programa deve ser simples, estruturado na abordagem (modular e descendente) do problema, e cumprir o objectivo a que se destina (ou seja, ser “formalmente correcto”). • Clareza: O programa deve reflectir a estrutura do algoritmo e permitir uma fa´cil detecc¸a˜o e correcc¸a˜o de erros. O programa deve, ainda, ser leg´ıvel e modifica´vel por outro programador. Nesse sentido deve atender-se a` separac¸a˜o em blocos funcionais, ao uso adequado das estruturas da linguagem, a` escolha cuidada de identificadores e a` documentac¸a˜o interna. • Eficieˆncia: A medida computacional de eficieˆncia de um programa depende do tempo que um programa leva a completar a tarefa a que esta´ destinado e do espac¸o de memo´ria necessa´rio a` sua execuc¸a˜o. O desenvolvimento de um programa deve ter estes dois factores em conta, sem contudo comprometer a clareza. Assim, o programa deve ser ra´pido e utilizar pouco espac¸o de memo´ria. 1.5 Exerc´ıcios Exerc´ıcio 1. Experimente cada um dos comandos a seguir, e os seus efeitos, numa janela de Shell, dita terminal (que e´ um “monitor” de comandos para o Sistema Operativo). mkdir cria uma directoria. rmdir apaga uma directoria. cp copia um ficheiro, na˜o destruindo o original. mv copia um ficheiro, destruindo o original. rm apaga um ficheiro. cd muda de directoria. ls lista o conteu´do de uma directoria. ls -l lista o conteu´do de uma directoria, em detalhe. 8 cat lista o conteu´do de um ficheiro. more lista o conteu´do de um ficheiro, pa´gina a pa´gina. man explica como funciona determinado comando. pwd indica qual e´ a directoria actual. No exerc´ıcio seguinte supo˜e-se que o utilizador ja´ criou uma directoria com o nome MP1 e um ficheiro de nome teste.p, escrito em Pascal. Ilustra-se como compilar esse ficheiro com o compilador de Pascal, fpc, atrave´s do terminal. O nome do programa executa´vel criado apo´s compilac¸a˜o sera´ teste. E´ ainda tambe´m criado um ficheiro adicional, teste.o. (Pode ver estes ficheiros atrave´s do comando ls -l.) ../MP1> fpc nome.p O executa´vel devera´ “correr” (executar) com a evocac¸a˜o do comando ./nome na janela Shell. Exerc´ıcio 2. Depois de dispor as janelas adequadas no seu ambiente de trabalho, edite, compile e execute os seguintes programas: 1) program zero; 2) program ola(output); begin begin end. writeln(’ola’); end. 3) program ola(output); 4) program ola(output); begin begin write(’ola’); writeln(’ola’); end. writeln; end. 5) program dois(output); 6) program dois_v2(output); begin begin writeln(2 + 2); write(’2 + 2 = ’); end. writeln(2 + 2); writeln(’2 + 2 = ’, 2 + 2); end. 7) program dois_v3(output, f); var f: text; begin assign(f, ’resultados.txt’); rewrite(f); writeln(’2 + 2 = ’, 2 + 2); writeln(f, ’2 + 2 = ’, 2 + 2); close(f); end. 8) program calculo(output, f); 9) program calculo(output); 9 var f: text; begin begin writeln(’ 2 + 3 / 4 = ’, 2 + 3 / 4); assign(f, ’resultados.txt’); writeln(’(2 + 3)/ 4 = ’, (2 + 3) / 4); rewrite(f); end. writeln(f, ’ 2 + 3 * 4 = ’, 2 + 3 * 4); writeln(f, ’(2 + 3)* 4 = ’, (2 + 3) * 4); close(f); end. 10) program soma(input, output); 11) program soma_v2(f, output); var x, y: integer; var f: text; begin x, y: integer; readln(x, y); begin writeln(x + y); assign(f, ’dados.txt’); end. reset(f); readln(f, x, y); close(f); writeln(x + y); end. 10 Cap´ıtulo 2 Conceitos fundamentais de programac¸a˜o imperativa 2.1 Introduc¸a˜o a` linguagem Pascal Uma linguagem de programac¸a˜o consiste num conjunto de regras, s´ımbolos e palavras especiais usadas para construir um programa. Podemos distinguir, • A sintaxe: regras formais que definem a construc¸a˜o de expresso˜es va´lidas numa linguagem. Estas sa˜o por vezes apresentadas em diagramas de sintaxe. Um programa e´ sintacticamente correcto se e so´ se corresponde a um caminho ao longo dos diagramas de sintaxe. • E a semaˆntica: conjunto de regras que da˜o o significado de uma expressa˜o da linguagem (forma de interpretar as expresso˜es da linguagem por forma a lhes dar um significado preciso). Suponhamos que pretendemos elaborar um programa que calcule a temperatura me´dia num determinado dia, dados os valores da temperatura mı´nima e da temperatura ma´xima. Resumindo, • Dados: Temperaturas mı´nima e ma´xima nesse dia. • Resultados: Temperatura me´dia nesse dia (ponto me´dio). • Problema: Calcular a temperatura me´dia num dia. Um programa em Pascal e´ constitu´ıdo por uma parte declarativa e uma parte operativa. Aten- dendo ao nosso objectivo, podemos escrever o seguinte co´digo fonte. { Programa que calcula a temperatura me’dia de um dia } program TempMedia(input, output); var tmin, tmax, tmedia: integer; begin writeln(’Temperatura mi’’nima?’); readln(tmin); writeln(’Temperatura ma’’xima?’); readln(tmax); tmedia := (tmin + tmax) div 2; writeln(’A temperatura me’’dia foi ’, tmedia); end. 11 Neste caso distinguimos o comenta´rio: { Programa que calcula a temperatura me’dia de um dia } uma directiva ignorada pelo compilador, mas importante para o programador manter uma docu- mentac¸a˜o adequada; a parte declarativa: program TempMedia(input, output); var tmin, tmax, tmedia: integer; que precede a parte operativa e serve para declarar o nome do programa, eventuais ficheiros ex- ternos utilizados, na segunda linha (o que forma o cabec¸alho do programa), e varia´veis ou outros identificadores utilizados pelo programa, na terceira linha; e a parte operativa (ou mo´dulo, ou bloco principal): begin writeln(’Temperatura mi’’nima?’); readln(tmin); writeln(’Temperatura ma’’xima?’); readln(tmax); tmedia := (tmin + tmax) div 2; writeln(’A temperatura me’’dia foi ’, tmedia); end. composta por blocos de instruc¸o˜es, cada uma separada da seguinte por “;”, e terminada pelo cara´cter “.”. Em alternativa os comenta´rios podem igualmente ser delimitados por “(*”, “*)”. A primeira instruc¸a˜o executa´vel writeln(’Temperatura mi’’nima?’) leva a que o computador apresente a mensagem “Temperatura mi’nima?” no dispositivo de sa´ıda (em geral o ecra˜), fazendo a comunicac¸a˜o com o utilizador do programa. A segunda instruc¸a˜o, readln(tmin) instrui o computador a obter um nu´mero atrave´s do dispositivo de entrada (geralmente o teclado) e a armazena´-lo na varia´vel chamada tmin. tmedia := (tmin + tmax) div 2 diz-se uma instruc¸a˜o de atribuic¸a˜o, e adiciona os valores de tmin e tmax, divide o resultado por 2 (divisa˜o inteira) e substitui por esse valor a varia´vel tmedia. Por fim, writeln(’A temperatura me’’dia foi ’, tmedia) permite que o computador mostre o resultado final, isto e´, o valor da varia´vel tmedia. Mostramos em seguida uma poss´ıvel execuc¸a˜o deste programa, Temperatura mi’nima?’20 Temperatura ma’xima?’27 A temperatura me’dia foi 23 Note-se que em linguagem Pascal, 12 • e´ obrigato´ria a declarac¸a˜o de todas as varia´veis a usar. • as instruc¸o˜es compostas (blocos) sa˜o delimitadas pelas palavras reservadas begin e end, sendo exemplo disso a parte operativa de um programa. Ao escrever um programa de computador e´ necessa´rio usar nomes que identifiquem as entidades que queremos manipular. Tais nomes sa˜o chamados identificadores e devem obedecer a um conjunto de regras, dependente da linguagem de programac¸a˜o. Em Pascal, um identificador e´ uma sequeˆncia de letras e d´ıgitos, iniciadas por uma letra, usadas para denominar qualquer entidade de um programa. Existe um conjunto de identificadores ja´ definidos, chamadosidentificadores reservados (palavras reservadas) ou identificadores standard : abs ln reset arctan eoln char sqrt write ord new boolean rewrite cos odd text readln get chr output integer sqr round pack input eof sin dispose maxint pred true succ false exp put unpack writeln read trunc page As sequeˆncias umaletra x1 num3ros sa˜o exemplos de alguns identificadores va´lidos. Notamos que, de modo a assegurar a clareza de um programa, os identificadores escolhidos devem ser sugestivos e ajudar a compreender o seu papel no programa. Observamos ainda que: • S´ımbolos especiais na˜o podem ser utilizados como identificadores. • Usando palavras reservadas o novo significado sobrepo˜e-se ao antigo. • Alguns compiladores analisam apenas os caracteres iniciais de um identificador, pelo que sequeˆncias muito longas podem ser confundidas. 2.1.1 Exerc´ıcios Exerc´ıcio 3. Edite, compile e execute o seguinte programa: 1. program calc_area (input, output); var lado, area: integer; begin writeln(’Este programa calcula a area de um quadrado.’); write(’Escreva a medida do lado : ’); readln(lado); area := lado * lado; writeln(’A area e’’ ’, area); end. 2. Altere o programa anterior de modo a calcular a a´rea de: a) um rectaˆngulo; b) um triaˆngulo; c) uma circunfereˆncia. 13 3. Verifique o que acontece com o programa para o ca´lculo da a´rea do rectaˆngulo se: a) introduzir nu´meros inteiros maiores do que 3500; b) introduzir um nu´mero real (na˜o inteiro); c) introduzir um cara´cter. Exerc´ıcio 4. 1. Sem compilar e executar, explique o efeito do seguinte programa. program circular(input, output); var a1, a2, a3: integer; aux: integer; begin {leitura de dados} write(’a1: ’); readln(a1); write(’a2: ’); readln(a2); write(’a3: ’); readln(a3); {?} aux:=a1; a1:=a2; a2:=a3; a3:=aux; {escrita de resultados} writeln(’a1 = ’,a1:1); writeln(’a2 = ’,a2:1); writeln(’a3 = ’,a3:1); end. 2. Confirme as suas afirmac¸o˜es da al´ınea anterior com a compilac¸a˜o e execuc¸a˜o do programa. 3. Altere as instruc¸o˜es de modo a obter um resultado final diferente. Exerc´ıcio 5. Corrija os erros em cada um dos programas abaixo e indique o resultado que produzem. 1) program euros(input); 2) program potencias(input, output); var escudos, euros: integer var n: integer; begin begin write(’Quantia em escudos: ’); write(’n: ’); readln(escudos); i := 1; Euros := 200.482 * escudos; while i < n do writeln(’Euros: , euros:7); begin end. writeln(i); i = 2 * i; end end. 14 Exerc´ıcio 6. Diga se as seguintes sequeˆncias de acc¸o˜oes podem ser consideradas algoritmos. Em caso afirmativo indique os dados necessa´rios e o resultado produzido. 1. numero1 ← 20 numero2 ← 10 repetir numero2 ← numero2 + numero1 ate´ numero1 = 0 2. numero1 ← 20 repetir numero2 ← numero2 + numero1 ate´ numero1 = 20 3. numero1 ← 20 numero2 ← 10 repetir numero2 ← numero2 + numero1 ate´ numero2 = 50 Exerc´ıcio 7. Indicando os dados e os resultados escreva um algoritmo que: 1. Calcule a soma dos 100 primeiros nu´meros positivos. 2. Calcule a soma dos 100 primeiros nu´meros ı´mpares positivos. 3. Receba uma sequeˆncia de nu´meros e determine se um dado nu´mero aparece nessa sequeˆncia. 4. Receba uma sequeˆncia crescente de nu´meros e verifique se esta conte´m um dado nu´mero. 5. Leia uma frase (cara´cter a cara´cter) e conte o nu´mero de vogais que esta conte´m. 6. Receba dois inteiros e determine se o primeiro e´ mu´ltiplo do segundo. 7. Receba um inteiro e determine se ele e´ um nu´mero primo. (Utilize o algoritmo da al´ınea anterior.) 8. Receba um inteiro e calcule todos os nu´meros primos menores do que ele pro´prio. (Utilize o algoritmo da al´ınea anterior.) 2.2 Tipos de dados O computador tem capacidade para armazenar e manipular informac¸a˜o de diversos tipos. A um conjunto de valores e um conjunto de operac¸o˜es que os manipulam chamamos um tipo de dados. 15 Estes podem ser classificados de acordo com o diagrama seguinte. Tipos Escalares Pre´-definidos integer real char boolean Definidos pelo utilizador Estruturados array record set file 2.2.1 Tipos elementares de dados pre´-definidos Os tipos de dados simples, ou elementares, sa˜o os fundamentais e mais comummente utilizados. Em Pascal sa˜o os tipos integer, real, char e boolean. Inteiros (integer) O tipo de dados integer inclui os nu´meros inteiros positivos, negativos e o zero. A representac¸a˜o destes valores e´ exacta, contudo o nu´mero de inteiros que e´ poss´ıvel representar, bem como o maior (menor) valor inteiro que pode ser representado e´ finito e dependente da ma´quina. Assim, o maior inteiro que e´ poss´ıvel representar e´ uma constante pre´-definida do Pascal, designada por MAXINT. Como referimos este valor pode variar, tipicamente e´ de 215 − 1, isto e´, 32 767. Operac¸o˜es com nu´meros inteiros que gerem valores inteiros maiores do que este valor (ou menores do que o seu sime´trico) podem produzir resultados absurdos. Para operar valores no domı´nio dos inteiros, existem va´rios operadores e func¸o˜es, dos quais apresentamos os mais comuns. • Operadores aritme´ticos com operandos e resultados inteiros: Operador Exemplo Operac¸a˜o + 5 + 3 = 8 adic¸a˜o - 2 - 9 = -7 subtracc¸a˜o (sime´trico) * 33 * 11 = 363 multiplicac¸a˜o div 21 div 4 = 5 quociente da divisa˜o inteira mod 21 mod 4 = 1 resto da divisa˜o inteira • Func¸o˜es standard com argumento e resultado inteiros: Func¸a˜o Exemplos Resultado abs abs(-6) = 6 valor absoluto sqr sqr(-3) = 9 quadrado succ succ(7) = 8, succ(-7) = -6 sucessor pred pred(10) = 9 predecessor • Constante pre´-definida: MAXINT, ma´ximo inteiro • Func¸o˜es com argumento inteiro e resultado real: Func¸a˜o Exemplo Resultado sqrt sqrt(3)=1.732050808 raiz quadrada • Operadores relacionais: 16 Operador Exemplo Operac¸a˜o = sqr(5) = 25 igualdade <> 2 <> 9 desigualdade < 45 < 1098 menor do que que > 17 >- 3 maior do que que >= 2 >= 2 maior do que ou igual a <= -6 <= 7 menor do que ou igual a Reais (real) O tipo de dados real permite operar e armazenar nu´meros reais, que incluem os inteiros ou outros com uma parte decimal. Este tipo permite armazenar valores com uma gama de variac¸a˜o muito maior do que a dos inteiros. Recordamos, no entanto, que uma vez que a representac¸a˜o interna e´ finita estes valores sa˜o muitas vezes aproximac¸o˜es, e na˜o valores exactos, donde operac¸o˜es sobre estes valores podem introduzir impreciso˜es. Por exemplo, 0.333333333 + 0.666666666 = 0.999999999 6= 1. Tal como para os inteiros, a grandeza e precisa˜o ma´ximas de valores reais que podem ser usados em Pascal dependem do computador. O separador decimal usado em Pascal e´ o “.”. Os nu´meros podem igualmente ser representados com uma notac¸a˜o semelhante a` notac¸a˜o cient´ıfica. Por exemplo, 12.5101 pode ser escrito como 12.5101, 1.25101E+1 ou 1.25101e1, e −0.0531 como -0.0531 ou -0.531E-1. A letra E, ou e, significa “10 elevado a”. Em muitas da operac¸o˜es aritme´ticas indicadas a seguir e´ suficiente que um dos operandos seja real para que o resultado seja um real. • Operadores aritme´ticos: Operador Exemplo Operac¸a˜o + 5.5+3=8.5, 5.5+3.0=8.5 adic¸a˜o - 2.2-9=-6.1 subtracc¸a˜o (sime´trico) * 33*0.5=11.5 multiplicac¸a˜o / 2.5/2=1.25, 5/4=1.25 divisa˜o real • Func¸o˜es com resultado real se o argumento for real: Func¸a˜o Exemplo Resultado abs abs(-6.5)=6.5, abs(-5)=5 valor absoluto sqr sqr(3.1)=9.61 poteˆncia • Func¸o˜es de transfereˆncia (com argumento real e resultado inteiro): Func¸a˜o Exemplo Resultado trunc trunc(-3.7)=-3, trunc(3.7)=3 truncatura roundround(-3.7)=-4, round(3.7)=4 arredondamento round(3.2)=3, round(-3.2)=-3 • Func¸o˜es com resultado real: 17 Func¸a˜o Exemplo Resultado cos cos(3)=0.98999, cos(3.1415)=1.0 cosseno sin sin(3)=0.14112, sin(3.1415)=0.0 seno arctan arctan(-1)=3.11415 arco de tangente sqrt sqrt(4)=2.0, sqrt(9.0)=3.0 raiz quadrada exp exp(1)=2.71828 exponencial ln ln(2.71828)=1.0, ln(1)=0.0 logaritmo nepperiano • Operadores relacionais: Operador Exemplo Operac¸a˜o = ????? igualdade <> desigualdade < menor do que > maior do que >= maior do que ou igual a <= menor do que ou igual a Caracteres (char) O tipo de dados char permite representar e operar caracteres, como letras, d´ıgitos ou s´ımbolos. O conjunto dos caracteres inclui A B C ... X Y Z a b c ... x y z 0 1 2 ... 9 + - * ( ) onde cada subsequeˆncia se encontra ordenada. A ordenac¸a˜o esta´ relacionada com a representac¸a˜o interna de caracteres, feita atrave´s de nu´meros naturais. Qualquer valor constante de um cara´cter e´ representado entre plicas, portanto: ’A’ 6= A (varia´vel) ’+’ 6= + (operador) ’5’ 6= 5 (numeral) As varia´veis do tipo char apenas podem conter um cara´cter. As constantes deste tipo podem conter sequeˆncias de caracteres, tambe´m conhecidas por strings, como por exemplo ’Ola mundo!’ ’Metodos de Programacao 1’ Para representar uma plica (“’”) e´ necessa´rio indicar duas (“’’”), uma vez, isoladamente, este cara´cter e´ utilizado para delimitar sequeˆncias de caracteres. Apresentamos a seguir alguns operadores e func¸o˜es usuais para operar valores no domı´nio dos caracteres. • Func¸o˜es de transfereˆncia: Func¸a˜o Exemplo Operac¸a˜o chr chr(48) = ’A’ cara´cter ord ord(’A’) = 48 nu´mero interno correspondente • Func¸o˜es com argumento e resultado char: Func¸a˜o Exemplo Operac¸a˜o succ succ(’R’) = ’S’ chr(ord(char)+1) pred pred(’a’) = ’Z’, pred(’A’) = ?? chr(ord(char)−1) 18 Lo´gicos (boolean) O tipo de dados boolean permite representar os valores lo´gicos TRUE e FALSE. Os operadores e valores lo´gicos seguem as tabelas de verdade, e seguem as mesmas regras gerais de avaliac¸a˜o do valor de verdade. Assim, temos • Operadores lo´gicos: Seguem tabelas de verdade e regras respectivas. Operador Operac¸a˜o and conjunc¸a˜o (∧) or disjunc¸a˜o (∨) not negac¸a˜o (¬) p q p and q p or q not p V V V V F V F F V F F V F V V F F F F V e, como exemplo, 1. x ∈]0, 1] ou x > 0 ∧ x ≤ 1, escreve-se: (x > 0) and (x <= 1) 2. (n > 1) and (n < 0) e´ falso 3. not (5 < 2) = true e´ verdadeiro • Func¸o˜es com argumento e resultado lo´gicos: Func¸a˜o Exemplo Operac¸a˜o pred pred(true)=false predecessor succ succ(false)=true sucessor • Func¸a˜o com argumento inteiro e resultado lo´gico: Func¸a˜o Exemplo Operac¸a˜o odd odd(5)=true, odd(2)=false ı´mpar • Func¸a˜o com argumento lo´gico e resultado inteiro: Func¸a˜o Exemplo Operac¸a˜o ord ord(true)=1, ord(false)=0 nu´mero interno Como exemplo da aplicac¸a˜o destes tipos de dados, e das respectivas operac¸o˜es, consideramos o programa a seguir, que opera dois valores dados sendo a operac¸a˜o a efectuar indicada atrave´s de um cara´cter. program calculadora(input, output); var operador: char; x, y, resultado: real; begin { Ler dados } write(’x, y?’); read(x, y); write(’operador?’); read(operador); { Efectuar calculo } case operador of ’+’: resultado := x + y; ’-’: resultado := x - y; ’*’: resultado := x * y; 19 ’/’: resultado := x / y end; { Escrever resultado } write(x, operador, y, ’=’, resultado) end. 2.2.2 Tipos definidos pelo utilizador Um programador pode definir um novo tipo de dados da seguinte forma: −→ type −→ identificador −→ = −→ tipo simples −→ ; −→ ; ....... ....... ....... .................. ............. ................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................. ....... ....... ....... Existem dois tipos de definic¸a˜o pelo utilizador, a definic¸a˜o por enumerac¸a˜o e a definic¸a˜o por sub- domı´nio. Definic¸a˜o por enumerac¸a˜o A definic¸a˜o de um tipo por enumerac¸a˜o e´ feita a partir de uma lista ordenada de constantes nomeadas pelo programador, de acordo com o diagrama de sintaxe −→ ( −→ identificador −→ ) −→ , ....... ....... ....... .................. ............. ........................................................................................................................................................................................................................................... ....... ....... ....... e tal como nos seguintes exemplos, type naipe= (ouros, copas, paus, espadas); premios= (primeiro, segundo, terceiro); dias= (segunda, terca, quarta, quinta, sexta, sabado, domingo); var trunfo: naipe; lugar: premios; d: dias; Notamos que type premios= (1o, 2o, 3o); na˜o e´ uma declarac¸a˜o de tipo correcta, ja´ que 1o, 2o e 1o na˜o sa˜o identificadores va´lidos. Relativamente a valores de um tipo definido por enumerac¸a˜o sa˜o va´lidos: • operadores relacionais: segunda < quinta • func¸o˜es pred, succ e ord: pred(quarta) = terca, succ(terca) = quarta, ord(terca) = 1, uma vez que ord(segunda)=0, ord(terca)=1, ord(quarta)=2, . . . 20 Definic¸a˜o por subdomı´nio A definic¸a˜o de tipos por subdomı´nio serve para restringir um domı´nio enumera´vel ja´ existente. Se as varia´veis tomam apenas alguns valores dum domı´nio definido e´ suficiente definir um novo tipo indicando o primeiro e o u´ltimo valores. −→ constante .. constante −→ Por exemplo, type NaoNegativo= 0 .. MAXINT; dias= (segunda, terca, quarta, quinta, sexta, sabado, domingo); DiasUteis= segunda .. sexta; var n: NaoNegativo; dia: DiasUteis; Com este tipo de definic¸a˜o herdam-se as operac¸o˜es e as func¸o˜es do domı´nio inicial. Se e´ feita uma atribuic¸a˜o fora do domı´nio declarado e´ emitida uma mensagem de erro. 2.3 Declarac¸a˜o de dados 2.3.1 Varia´veis Uma varia´vel e´ um objecto num programa cujo valor poder ser alterado durante a execuc¸a˜o, de acordo com as instruc¸o˜es especificadas. −→ var −→ identificador −→ : −→ tipo −→ ; −→ , ....... ....... ....... .................. ............. ....................................................................................................................................................................................................................................................... ....... ....... ....... ................................. ...... ....... ...... .............................................................................................................................................................................................................................................................................................................................................................................................................................................................. ....... ....... ................... .............. A sua declarac¸a˜o no programa deve conter um identificador, nome pelo qual sera´ representada, e o tipo de valores que podera´ conter. A declarac¸a˜o de varia´veis antes dum bloco de instruc¸o˜es sobre elas e´ obrigato´ria e permite a reserva antecipada das ce´lulas de memo´ria que podem vir a ser usadas, o que depende do nu´mero e dotipo das varia´veis. Como exemplo de tais declarac¸o˜es podemos ter var x, y: real; n: integer; d: DiasUteis; Veremos adiante que o valor de uma varia´vel pode ser modificado atrave´s de instruc¸o˜es de atribuic¸a˜o ou instruc¸o˜es de leitura. 2.3.2 Constantes Um literal e´ um valor constante utilizado num programa. Por exemplo, dobro := 2 * x; Uma constante pode ser vista como uma varia´vel, uma vez que esta´ associada a um espac¸o na memo´ria do computador, mas que na˜o e´ modificada ao longo de um programa. −→ const −→ identificador −→ = −→ constante −→ ; −→.... ....... ....... ....... .............. ............. ....................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... ....... ....... ....... 21 E´ necessa´rio definir os nomes e os valores das constantes a utilizar no programa, o que deve ser feito na parte de declarac¸o˜es. O tipo da constante fica definido automaticamente atrave´s do seu valor. Seguem-se alguns exemplos de declarac¸a˜o de constantes, const pi = 3.1415926; titulo = ’Alice no Pais das Maravilhas’; delta = 0.5E-06; iva = 0.23; O identificador da constante pode ser substitu´ıdo pelo seu valor, contudo ha´ vantagens em manter a utilizac¸a˜o de constantes, • podemos escolher identificadores sugestivos daquilo que a constante representa; • e´ mais simples alterar o valor de uma constante do que modificar todas as ocorreˆncias de um valor no programa. Ale´m disso o valor da constante na˜o pode ser alterado ao longo do programa, uma tentativa nesse sentido origina uma mensagem de erro. 2.4 Expresso˜es aritme´ticas e lo´gicas As expresso˜es fornecidas ao computador sa˜o avaliadas, para os seus resultados serem usados posteri- ormente. Para realizar o ca´lculo destas expresso˜es e´ necessa´rio estabelecer uma ordem de avaliac¸a˜o das mesmas. Uma expressa˜o aritme´tica ou lo´gica conte´m operandos e operadores, o que em Pascal se traduz em varia´veis, constantes e operadores. O resultado de uma expressa˜o tem um tipo, que depende dos operandos e das operac¸o˜es. Quando surgem varia´veis e constantes do tipo integer e do tipo real a avaliac¸a˜o e´ feita frequentemente usando aritme´tica real apo´s a conversa˜o dos valores inteiros em reais. Nesses casos o resultado e´ do tipo real Se a expressa˜o conte´m um u´nico operador, os operandos comec¸am por ser avaliados e so´ enta˜o e´ realizada a operac¸a˜o em causa. Se esta˜o envolvidos mais do que um operador e´ necessa´rio definir a ordem pela qual as operac¸o˜es correspondentes sera˜o avaliadas, para que na˜o exista ambiguidade numa tal avaliac¸a˜o. Essa ordem e´ definida pela prioridade dos operadores envolvidos, e que e´ semelhante a` utilizada em expresso˜es matema´ticas. Operador Prioridade not 4 *, /, div, mod, and 3 +, -, or 2 =, <>, >, >=, <, <= 1 Assim, tal como na avaliac¸a˜o de expresso˜es alge´bricas, • a avaliac¸a˜o realiza-se por ordem na˜o crescente de prioridade dos operadores, • para operadores de igual prioridade, as avaliac¸o˜es realizam-se da esquerda para a direita. Por exemplo, • 10 div 2 * 3 = 5 * 3 = 15 22 • 5 * 2 / 4 * 2 = 10 / 4 * 2 = 2.5 * 2 = 5.0 • (3 > 0) and not (3 < 10) = true and not true = true and false = false Para contrariar estas regras, e obrigar a que algumas operac¸o˜es tenham prioridade sobre as restantes, podem ser usados pareˆntesis (equilibrados), “(” e “)”. Por exemplo, • 10 div (2 * 3) = 10 div 6 = 1 • 5 * 2 / (4 * 2) = 5 * 2 / 8 = 10 / 8 = 1.25 Ficam algumas observac¸a˜oes sobre a escrita e o ca´lculo de expresso˜es aritme´ticas e lo´gicas em Pascal, • As varia´veis de uma expressa˜o ja´ devem ter um valor no momento de avaliac¸a˜o da expressa˜o. • O operador de multiplicac¸a˜o “*” na˜o pode ser omitido na escrita. • Em caso de du´vida sobre a prioridade dos operadores devem usar-se pareˆntesis. 2.4.1 Exerc´ıcios Exerc´ıcio 8. Indique o tipo de dados final e calcule o valor de cada uma das expresso˜es: 1. 2 + 3 * 2 + 3 * 4 2. sqr(3) 3. sqr(3.0) 4. trunc(-9.5) 5. round(9.5) 6. -round(9.5) 7. 5 div 2 8. 5 / 2 9. 128 div 3 mod 5 10. 128 mod 5 div 3 11. 183 mod 18 div 3 * 128 12. (8 div 5) / (8 mod 5) Exerc´ıcio 9. Tendo em conta a tabela: varia´vel a b c d tipo real real integer integer valor 5.7 6.3 5 4 determine o tipo e o valor de cada uma das expresso˜es seguintes: 1. sqr(a+b)/(c+d) 2. c * (c mod d) 3. (c mod d)/2 4. trunc(a-b) 5. trunc(a-b) div c 6. exp(2 * ln(c)) 7. (c div d)/(-a) 8. trunc(abs(cos(b))) mod 1 9. 2 * (b-a) Exerc´ıcio 10. Coloque o nu´mero mı´nimo de pareˆntesis na expressa˜o: 16.4− 51.0 / 4.8 ∗ 0.6 + 74.92 de modo que as operac¸o˜es sejam efectuadas pela ordem indicada em cada uma das al´ıneas: (a) −+ ∗/ (b) ∗+ /− (c) /−+∗ Exerc´ıcio 11. Proceda de modo ana´logo ao do problema anterior relativamente a` expressa˜o: 22 + 16 ∗ 100 mod 12− 9 div 4 e de forma que as operac¸o˜es sejam efectuadas pelas seguintes ordens: (a) + mod ∗ div - (b) div - mod ∗ + (c) − mod div ∗ + 23 2.5 Instruc¸o˜es 2.5.1 Instruc¸a˜o de atribuic¸a˜o A instruc¸a˜o de atribuic¸a˜o atribui o valor de uma expressa˜o a uma varia´vel. → varia´vel → := → expressa˜o → O operador de atribuic¸a˜o e´ “:=”, a` sua direita e´ escrita a expressa˜o a avaliar, e a` esquerda e´ indicado o identificador da varia´vel onde o resultado encontrado e´ armazenado. O valor da expressa˜o sobrepo˜e- se ao valor na zona de memo´ria identificada pelo identificador que a varia´vel pudesse, eventualmente, ter antes de executada a instruc¸a˜o de atribuic¸a˜o. Varia´vel e expressa˜o teˆm que ser do mesmo tipo (excepto na atribuic¸a˜o de um valor inteiro a uma varia´vel real). Com as declarac¸o˜es var i: integer; x: real; teste: boolean; letra: char; temos os seguntes exemplos de atribuic¸o˜es i := 3; letra := chr(i); teste := True; x := x + i + 10 Mostramos em seguida algumas sequeˆncias de instruc¸o˜es muito frequentes, como a troca dos valores de duas varia´veis e o incremento de uma varia´vel. Consideramos as seguintes declarac¸o˜es var i, j, aux: integer; • Troca dos valores de duas varia´veis (necessariamente do mesmo tipo): aux := i; i := j; j := aux Se i = 2 e j = 5, enta˜o o conjunto de instruc¸o˜es produz i = 5 e j = 2. • Incrementar o valor de uma varia´vel: i := i + 1 Considerando inicialmente i = 1, esta instruc¸a˜o produz i = 2. 2.5.2 Instruc¸a˜o de sequenciac¸a˜o A instruc¸a˜o de sequenciac¸a˜o separa duas instruc¸o˜es e especifica a sua ordem de execuc¸a˜o, executando- as sequencialmente. Para este efeito, • o s´ımbolo “;” delimita o fim de uma instruc¸a˜o e serve de separador de instruc¸o˜es; 24 • um grupo de instruc¸o˜es, ou seja, um bloco de instruc¸o˜es, e´ delimitado pelas palavras reservadas begin e end (obrigatoriamente equilibradas). → begin → instruc¸a˜o → end → ; → ; ....... ....... ....... .................. ............. ..................................................................................................................................................................................................... ....... ....... ....... So´ apo´s conclusa˜o de uma instruc¸a˜o se executa a seguinte. Por exemplo, instruc¸~ao 1; instruc¸~ao 2; instruc¸~ao 3; ; instruc¸~ao 5 significa que sa˜oexecutadas cinco instruc¸o˜es, pela ordem 1, 2, 3, 4 e 5. A instruc¸a˜o 4 e´ nula. Outro exemplo, utilizando treˆs blocos de instruc¸o˜es, e´ begin instruc¸~ao 1; begin instruc¸~ao 2; begin instruc¸~ao 3; ; end; end; instruc¸~ao 5 end; Para facilitar a leitura do programa e, em particular, facilitar a identificac¸a˜o das instruc¸o˜es contidas em cada bloco deve utilizar-se uma indentac¸a˜o adequada. O conjunto de instruc¸o˜es a seguir e´ interpretado da mesma forma que o anterior, apesar da diferente exposic¸a˜o. begin instruc¸~ao 1; begin instruc¸~ao 2; begin instruc¸~ao 3; ; end; end; instruc¸~ao 5 end; 2.5.3 Instruc¸o˜es de entrada/sa´ıda As instruc¸o˜es de entrada/sa´ıda sa˜o utilizadas para recolha de dados e escrita de resultados. → program → identificador → ( → identificador → ) → ; → , ....... ....... ....... .................. ............. ........................................................................................................................................................................................................................................... ....... ....... ....... Em geral sa˜o utilizados para entrada e sa´ıda de dados os ficheiros ditos standard : 25 • input: que representa o teclado; • output: que representa o ecra˜. Contudo, num programa que apenas receba dados, sem devolver nada para o exterior, podemos declarar somente program Exemplo1(input); ou, vice-versa, program Exemplo2(output); Ale´m destes ficheiros standard podemos tambe´m usar outros existentes em memo´ria, desde que declarados convenientemente. Analisamos em seguida instruc¸o˜es de leitura e instruc¸o˜es de escrita para trabalhar com ficheiros de entrada de dados e de sa´ıda de resultados. Nesse caso poder´ıamos ter program Exemplo(dados, resultados); Instruc¸o˜es de entrada: Leitura A leitura de varia´veis e´ uma alternativa a` instruc¸a˜o de atribuic¸a˜o que permite modificar o seu valor. → read → ( −−−−−−− → lista varia´veis →) → readln ...................................................... .................................................................. .......... ..................................... ...... ....... ...... canal → , ................................. ....... ....... ....... .................................................................. .......... ..................................... ...... ....... ...... Os valores obtidos atrave´s do canal de entrada sa˜o atribu´ıdos, pela mesma ordem, a`s varia´veis na instruc¸a˜o de leitura. As varia´veis a ler e os valores dados teˆm que ser do mesmo tipo. Alguns exemplos da utilizac¸a˜o destas instruc¸o˜es sa˜o: • read(i,j) faz a leitura das varia´veis i e j a partir do teclado, e tem o mesmo efeito que read(input,i,j); • read(dados1,i,j) faz a leitura das varia´veis i e j a partir do ficheiro dados1; • readln(i,j) (ou readln(input,i,j)) e readln(dados1,i,j) produzem o mesmo efeito que os pontos anteriores, mas mudando a linha apo´s a leitura. Estas instruc¸o˜es permitem ler valores: • nume´ricos: ignorando espac¸os em branco e mudanc¸as de linha; e • caracteres: um de cada vez. Como exemplo considerem-se as declarac¸o˜es var x: real; c1, c2, c3: char; n: integer; Enta˜o, dada a sequeˆncia 6.5 a123 a instruc¸a˜o read(x,c1,c2,c3,n) 26 produz: x = 6.5, c1 = ’ ’, c2 = ’a’, c3 = ’1’, n = 23 E´ de notar que um nu´mero (inteiro ou real) deve ser seguido de um espac¸o em branco ou uma mudanc¸a de linha. Mostramos ainda alguns exemplos que permitem distinguir as leituras feitas a partir das instruc¸o˜es read e readln, considerando as varia´veis var n1, n2, n3: integer; e os dados de entrada 5 11 7 2 9 Enta˜o, para cada conjunto de instruc¸o˜es de leitura ter´ıamos os valores de n1, n2 e n3 indicados em seguida, Instruc¸o˜es n1 n2 n3 readln(n1,n2); readln(n3); 5 11 2 read(n1,n2); readln(n3); 5 11 7 readln; readln(n1,n2); 2 9 ? readln(n1); read(n2); readln(n3); 5 2 9 Por fim, notamos que os valores de varia´veis do tipo boolean na˜o podem ser obtidos directamente com as instruc¸o˜es de leitura acima. Instruc¸o˜es de sa´ıda: Escrita Tal como as instruc¸o˜es de leitura read e readln, as instruc¸o˜es de escrita write e writeln rece- bem uma lista de paraˆmetros a imprimir, entre pareˆntesis e separados por v´ırgulas. Contudo, os paraˆmetros a imprimir podem ser expresso˜es aritme´ticas ou lo´gicas. → write → ( −−−−−−− → lista de sa´ıda →) → writeln ...................................................... .................................................................. .......... ..................................... ...... ....... ...... canal → , ................................. ....... ....... ....... .................................................................. .......... ..................................... ...... ....... ...... Alguns exemplos da utilizac¸a˜o destas instruc¸o˜es sa˜o: • write(i,j) imprime no ecra˜ o valor das varia´veis i e j, e tem o mesmo efeito que write(output,i,j); • write(res1,i,j) faz a escrita dos valores de i e j no ficheiro res1; • writeln(i,j) (ou writeln(output,i,j)) e writeln(res1,i,j) produzem o mesmo efeito que os pontos anteriores, mas mudando a linha apo´s a escrita. Dadas as varia´veis x = 5.0, c1 = ’g’, n = 3, teste = True, temos: Instruc¸o˜es Sa´ıda write(n) ou write(3) 3 write(n+2*x) ou write(13) +1.300000E+01 write(c1) ou write(’g’) g write(’Uma string’) Uma string write(teste) ou write(2 > 1) True 27 O formato com que aparece cada informac¸a˜o pode ser modificado por utilizac¸a˜o de um especifi- cador de formato. Este e´ constitu´ıdo por express~ao : comprimento do campo : parte decimal onde • express~ao e´ a informac¸a˜o a ser escrita, • comprimento do campo e´ o tamanho, isto e´, o nu´mero de colunas, mı´nimo do campo para escrever s´ımbolos (que e´ alargado automaticamente quando insuficiente), • parte decimal e´ o nu´mero de casas decimais a apresentar, para valores reais. Nos exemplos a seguir o cara´cter “ ” assinala a impressa˜o de um espac¸o em branco. Dadas as varia´veis x = -9.0 e n = 3, temos Instruc¸o˜es Sa´ıda write(x:6:2) -9.00 write(x:3:2) -9.00 write(n:3) 3 write(x:6:2); write(n:1) -9.003 enquanto que a instruc¸a˜o: write(’Inteiro ’:2, n:3, ’ e real ’:10, x:4) produz como sa´ıda Inteiro 3 e real -9.0 A instruc¸a˜o writeln pode ser utilizada sem argumentos, produzindo enta˜o a impressa˜o de um cara´cter de mudanc¸a de linha. 2.5.4 Exerc´ıcios Exerc´ıcio 12. 1. Diga se cada uma das atribuic¸o˜es seguintes e´ ou na˜o va´lida, supondo feitas as declarac¸o˜es, var m, n: integer; a, b: real; Em caso negativo proponha uma modificac¸a˜o que torne a referida instruc¸a˜o va´lida: (a) m := trunc(B); (b) m := trunc(b) + a; (c) p := m - n; (d) m := n mod a; (e) b := 2.99 * 10; (f) b := 2.99 * 109; (g) n := a - trunc(a); (h) ma elec := 0.910956E-27; (i) ab := a * b; (j) a := (.5E+2-1); (k) a := m / n; (l) b := 4 + 2a; 2. Escreva programas que permitam verificar a correcc¸a˜o das suas respostas. Exerc´ıcio 13. 1. Escreva uma instruc¸a˜o de atribuic¸a˜o para cada uma das seguintes acc¸o˜es: 28 (a) O contador I e´ incrementado de uma unidade. (b) M e´ uma co´pia do valor de N. (c) I e´ o valor arredondado do real X. (d) I e´ o maior inteiro inferior ou igual a X, positivo. (e) M e´ o inteiro mais pro´ximo da me´dia dos reais A e B. (f) A varia´vel t30 toma o valor da tangente de 30 graus. (g) Dado n ∈ ZZ− {0}, a varia´vel inteira SINAL toma o valor 1 se n > 0, e −1 se n < 0. (h) U toma o valor do algarismo das unidades do real X. (i) R toma o valor de √ x se x ≥ 0, ou de √−x caso contra´rio.(j) Z toma o valor de Y X . (k) ALFA e´ o aˆngulo (em graus) cuja tangente e´ x. (l) y ← y + 4x+ 3x2 + 2x3 + x4 (procure minimizar o nu´mero de operac¸o˜es). (m) y ← sin(ax) 2a cos2(ax) . (n) A a´rea de um pol´ıgono regular com n lados de comprimento b, dada por area← nb 2 4 cotg pi n . (o) raiz3de5← 3 √ x5. (p) z ← log6(3x2 + 6). (q) fraccao← a+ d e+ d e+ fg . (r) x← ( √ a2 + b2 − a)4 4 √ a2 + b2 . 2. Escreva programas que permitam verificar a correcc¸a˜o das suas respostas. Exerc´ıcio 14. Diga o tipo e calcule o valor de cada uma das expresso˜es seguintes, supondo que k e´ uma varia´vel do tipo inteiro, p e q sa˜o varia´veis lo´gicas e x e´ do tipo real. 1. (pred(4)-succ(2)) mod 4 + sqrt(4) = 8 2. not(p or q) = not p and not q 3. not(p and q) = not(not p or not q) 4. (p and (q and not q)) or not (q or true) 5. (round(-6.5) < trunc(-6.5)) or p 6. (round(sin(x))=0) or (abs(round(sin(x)))=1) 7. not((3 mod 2 = 1) and (7 < 5)) 8. ord(’D’)-ord(’B’) 9. succ(’E’) 10. odd(k) or odd(k+1) 11. ord(’5’)-ord(’0’) 12. chr(ord(’C’)+3) Exerc´ıcio 15. Diga se cada uma das atribuic¸o˜es seguintes e´ ou na˜o va´lida, supondo feitas as de- clarac¸o˜es, const espaco = ’ ’; var m, n: integer; a, b: real; p, q: boolean; c1, c2: char; 29 Em caso negativo proponha uma modificac¸a˜o que torne a referida instruc¸a˜o va´lida: 1. c1 := espaco; 2. c1 := ’a’; 3. c1 := c2; 4. c1 := ’c2’; 5. ’c’ := c2; 6. ’c2’ := chr(’a’); 7. m := m-ord(’0’); 8. p := (m + n) > 0; 9. ’a’ := chr(ord(’b’)+1); 10. b := ord(c1)+ord(c2); 11. m := succ(c1); 12. n := ord(c1)+succ(5); 13. p := q and (ord(c1) <> ’a’); 14. p := q and (ord(’a’) >= 40); Exerc´ıcio 16. Escreva uma instruc¸a˜o de atribuic¸a˜o para cada uma das seguintes acc¸o˜es: 1. A varia´vel L e´ verdadeira sse L1 e L2 forem ambas falsas. 2. A varia´vel MAIOR e´ verdadeira se X e´ maior que Y e e´ falsa no caso contra´rio. 3. A varia´vel L e´ verdadeira sse L1 e´ verdadeira mas na˜o L2. 4. Meio e´ verdadeira sse M for o metade de N. 5. VAbs e´ verdadeira sse os inteiros K e M forem iguais em valor absoluto. 6. A varia´vel Cons e´ verdadeira sse a varia´vel cara´cter LETRA for uma consoante minu´scula. 7. A varia´vel XOR e´ verdadeira sse apenas uma das varia´veis B1 ou B2 for verdadeira. 8. A varia´vel PAR e´ verdadeira sse o inteiro N e´ par. 9. A varia´vel MULT e´ verdadeira sse I for mu´ltiplo de J (I e J sa˜o do tipo inteiro). 10. A varia´vel VOG e´ verdadeira sse o cara´cter C e´ uma vogal. 11. RComplex e´ verdadeira sse a equac¸a˜o ax2 + bx+ c = 0 na˜o tem ra´ızes complexas. 12. Sendo N uma varia´vel do tipo char, DIG e´ verdadeira sse N representa um algarismo. 13. A varia´vel inteira PAR e´ 1 se n for par e 2 se n e´ ı´mpar. 14. A varia´vel inteira ALTERNADA toma o valor de (−1)n, com n ∈ ZZ. 15. Sendo c um cara´cter que representa um d´ıgito, atribuir a N o valor nume´rico desse d´ıgito (N ∈ {0, . . . , 9}). Exerc´ıcio 17. Elabore os seguintes programas, separando as va´rias partes em secc¸o˜es de texto distintas por curtos comenta´rios, e.g. {leitura de dados} ... {ca´lculo} ... {escrita de resultados} ..., e na˜o esquecendo de usar indentac¸a˜o sempre que adequado: 1. Converta graus Celsius em graus Fahrenheit. O programa deve: • indicar o seu objectivo; • ler o valor da temperatura em graus Celsius, C; • calcular o valor correspondente em graus Fahrenheit, F , sabendo que F = 1.8C + 32; • escreva o valor de F . 30 2. Calcule a a´rea de um pol´ıgono (regular) de n lados com comprimento b, sabendo que esse valor e´ dado por: A = 1 4 nb2cotg( pi n ) . Para isso: • escreva uma mensagem indicadora do que o seu programa vai fazer; • leia o nu´mero de lados n e o comprimento b; • escreva o valor da a´rea calculada. 3. Calcule o lucro obtido na venda de um produto. Para isso: • leia o co´digo do produto, o nu´mero de unidades vendidas, os prec¸os unita´rios de custo e de venda, e o IVA a pagar (em percentagem - inteiro); • calcule o lucro total apurado; • escreva o co´digo do produto e o respectivo lucro na forma EUR. . . . . . , . Note que, o valor de IVA que o comerciante tem de pagar e´ calculado sobre a diferenc¸a entre o prec¸o de custo e o de venda. 4. Transforme coordenadas polares em cartesianas: • leia os valores das coordenadas cartesianas a transformar, x e y; • calcule o valor das coordenadas polares ρ e θ correspondentes a`s coordenadas cartesianas x e y, sabendo que ρ = √ x2 + y2 e θ = arctg(y/x); • escreva as novas coordenadas bem identificadas. Exerc´ıcio 18. Fac¸a um programa que pec¸a ao utilizador um real a, calcule o valor de f(a), onde f(x) = e−x/δ δ , considerando que δ e´ fixo e igual a 2. O programa deve imprimir o resultado no ecra˜. Exerc´ıcio 19. Escreva um programa que pec¸a ao utilizador um inteiro n e um real a, calcule g(n, a), onde g(k, x) = (−1)k+1 logk |x|, e escreva o resultado. 2.6 Estruturas de controlo Estruturas de controlo sa˜o instruc¸o˜es especiais em Pascal, que permitem controlar o fluxo de uma sequeˆncia de instruc¸o˜es, alterando a ordem sequencial expl´ıcita. Estas alterac¸o˜es podem surgir por motivos diversos. As estruturas de controlo podem ser classificadas segundo o diagrama seguinte. Estruturas de Base Sequeˆncia Selecc¸a˜o { Alternativa Mu´ltipla Repetic¸a˜o EnquantoAte´ que Com contador Subprograma { Procedimento Func¸a˜o 31 2.6.1 Instruc¸o˜es de selecc¸a˜o Instruc¸o˜es de selecc¸a˜o: if-then-else A selecc¸a˜o alternativa permite escolher instruc¸o˜es a executar consoante o valor de uma expressa˜o lo´gica. Se a expressa˜o e´ verdadeira, e´ executada a instruc¸a˜o correspondente a then, sena˜o e´ executada a instruc¸a˜o correspondente a else. A parte da instruc¸a˜o relativa ao else e´ facultativa. No caso de esta na˜o existir, se a expressa˜o lo´gica tem valor falso passa-se a` instruc¸a˜o seguinte. −→ if −→ expressa˜o lo´gica −→ then −→ instruc¸a˜o −→ else −→ instruc¸a˜o −→ ................................. ....... ....... ....... ......................................................................................................................................................................................................................................................................................................... ...... ....... ...... E´ importante salientar que a palavra else na˜o pode ser precedida do separador de instruc¸o˜es “;”. Em alternativa, se e´ necessa´ria mais do que uma instruc¸a˜o antes do else, deve utilizar-se o delimitador de blocos begin-end. Como exemplo tomemos o problema de ler dois nu´meros inteiros e efectuar a sua divisa˜o, tambe´m inteira. Uma implementac¸a˜o simples seria writeln(’x, y? ’); readln(x,y); res := x div y; writeln(x, ’ / ’, y, ’ = ’, res) o que, apesar de sintacticamente correcto, geraria um erro de execuc¸a˜o se fosse introduzido o valor zero como divisor. Uma versa˜o alternativa a estas instruc¸o˜es executa a divisa˜o entre dois inteiros, desde que o divisor seja na˜o nulo. writeln(’x, y? ’); readln(x,y); if y <> 0 then begin res := x / y; writeln(x, ’ / ’, y, ’ = ’, res) end Ainda uma terceira possibilidade acrescenta uma mensagem indicadora de que o quociente na˜o e´ calculado se o divisor for nulo. writeln(’x, y? ’); readln(x,y); if y <> 0 then begin res := x / y; writeln(x, ’ / ’, y, ’ = ’, res) end else writeln(’Erro! O divisor e’’ nulo.’) Consideremos o problema de, dados treˆs inteiros positivos, verificar se estes podem ser o compri- mento dos lados dum triaˆngulo e, se assim for, classificar o triaˆngulo. Neste caso, Dados: treˆs inteirospositivos, Resultados: informac¸a˜o sobre se foi definido um triaˆngulo, e a sua classificac¸a˜o. 32 Para definir a resoluc¸a˜o do problema interessa recordar que treˆs inteiros positivos sa˜o lados de um triaˆngulo se cada um e´ menor do que a soma dos restantes dois. Ale´m disso, dizemos que um triaˆngulo e´, • equila´tero se os lados teˆm todos igual comprimento; • iso´sceles se apenas dois lados teˆm comprimento igual; • escaleno se os lados teˆm todos comprimentos diferentes. Podemos enta˜o escrever o seguinte programa program triangulo (input, output); var a, b, c: 1 .. MAXINT; begin writeln(’a, b, c?’); readln(a, b, c); if (a < b + c) and (b < a + c) and (c < a + b) then if (a = b) or (a = c) or (b = c) then if (a = b) and (b = c) then writeln(’Triangulo Equilatero’) else writeln(’Triangulo Isosceles’) else writeln(’Triangulo Escaleno’) else writeln(’Nao formam um triangulo’) end. Suponhamos que sa˜o declaradas treˆs varia´veis a, b e b, do mesmo tipo, e que pretendemos atribuir um valor inteiro a uma quarta varia´vel, max, de acordo com as instruc¸o˜es seguintes, max := -1; if a > b then if a > c then max := a else max := 0 Com a informac¸a˜o que temos ate´ ao momento na˜o podemos saber se o u´nico else nas instruc¸o˜es deve ser executado em alternativa ao primeiro ou ao segundo if. Este assunto e´ conhecido como problema do else pendente. Mesmo tomando valores concretos para a, b e c e´ necessa´rio estabelecer uma regra que permita afirmar qual o valor de max apo´s as instruc¸o˜es. Notemos que neste caso a utilizac¸a˜o da indentac¸a˜o errada pode ser enganadora. De facto para o compilador de Pascal a versa˜o anterior, max := -1; if a > b then if a > c then max := a else max := 0 ou 33 max := -1; if a > b then if a > c then max := a else max := 0 resumem-se ao mesmo. Por convenc¸a˜o o else esta´ associado ao if mais pro´ximo, o que significa que a indentac¸a˜o correcta seria a segunda. Se a = 1, b = 5 e c = 10 enta˜o max = -1, enquanto que se a = 20, b = 5 e c = 10 enta˜o max = 0. Para contrariar esta regra, e forc¸ar o else a associar-se ao primeiro if, devemos utilizar as palavras begin e end, como em max := -1; if a > b then begin if a > c then max := a end else max := 0 Neste caso, se a = 1, b = 5 e c = 10 enta˜o max = 0, enquanto que se a = 20, b = 5 e c = 10 enta˜o max = -1. Instruc¸o˜es de selecc¸a˜o: case Por vezes torna-se conveniente uma escolha mu´ltipla, isto e´ com mais do que duas alternativas. Nesses casos e´ poss´ıvel utilizar va´rias instruc¸o˜es de selecc¸a˜o alternativa, mas tal torna a leitura do co´digo demasiado pesada. A selecc¸a˜o mu´ltipla permite a escolha de instruc¸o˜es a executar consoante o valor de uma constante que pode ter mais do que dois valores. → case → expressa˜o → of → constante → : → instruc¸a˜o → end → , ; ................................. ...... ....... ...... .............................................................................................................................................................................................. ....... ....... ....... ................................................................................... ...... ....... ...... ....................................................................................................................................................................................................................................................................................................................................................................................................................................................................... ....... ....... ....... Por exemplo, case i of 1 : instrucao1; 2 : begin instrucao2; instrucao3 end; 3, 4: instrucao4 end A expressa˜o tem tambe´m o nome de selector e tem de ser de um tipo enumera´vel (portanto excluindo o tipo real). Ale´m disso selector e constantes teˆm de ser do mesmo tipo. Notamos ainda que a palavra end que termina a estrutura case-of na˜o esta´ associada a nenhum begin. Se a mesma constante aparece associada a mais do que uma instruc¸a˜o, surge um erro de com- pilac¸a˜o. Se, pelo contra´rio, o valor do selector na˜o corresponde ao de nenhuma das constantes, enta˜o 34 surge um erro de execuc¸a˜o. Para excluir tais valores alguns compiladores de Pascal admitem a pala- vra otherwise, ou else, como “constantes” alternativas a`s definidas. Em Pascal standard podemos contornar esta questa˜o pela utilizac¸a˜o de um if-then-else, como veremos em seguida. Como exemplo suponhamos que pretendemos fazer corresponder uma mensagem a uma classi- ficac¸a˜o que pode ter os valores A, B, C, D ou F. Uma soluc¸a˜o para este problema pode ser case nota of ’A’, ’B’: writeln(’Bom trabalho!’); ’C’ : writeln(’Trabalho normal.’); ’D’, ’F’: writeln(’Mau trabalho...’) end Para tornar estas intruc¸o˜es mais robustas, prevenindo a introduc¸a˜o de valores que na˜o os das cons- tantes, podemos reformular esta implementac¸a˜o, acrescentando uma instruc¸a˜o if-then-else, if (nota = ’A’) or (nota = ’B’) or (nota = ’C’) or (nota = ’D’) or (nota = ’F’) then case nota of ’A’, ’B’: writeln(’Bom trabalho!’); ’C’ : writeln(’Trabalho normal.’); ’D’, ’F’: writeln(’Mau trabalho...’) end else writeln(’A nota dada nao e valida’) ou mesmo if (nota = ’A’) or (nota = ’B’) or (nota = ’C’) or (nota = ’D’) or (nota = ’E’) or (nota = ’F’) then case nota of ’E’ : ; ’A’, ’B’: writeln(’Bom trabalho!’); ’C’ : writeln(’Trabalho normal.’); ’D’, ’F’: writeln(’Mau trabalho...’) end else writeln(’A nota dada nao e valida’) Por fim mostramos como transformar estas instruc¸o˜es utilizando apenas estruturas if-then-else, if (nota = ’A’) or (nota = ’B’) then writeln(’Bom trabalho!’) else if (nota = ’C’) then writeln(’Trabalho normal.’) else if (nota = ’D’) or (nota = ’F’) then writeln(’Mau trabalho!’) else writeln(’A nota dada nao e valida’) 35 2.6.2 Exerc´ıcios Exerc´ıcio 20. Escreva um programa que pec¸a ao utilizador dois nu´meros reais a e b, calcule o valor de f(a, b), com: f(x, y) = { (xy + x−y)2 se x > 0 0 se x ≤ 0 e escreva o resultado. Exerc´ıcio 21. Preveja o resultado e correspondente sa´ıda do seguinte programa. program experiencias (input, output); var letra: char; n: integer; begin write(’Escreva um inteiro entre 1 e 26: ’); readln(n); if (n>=1) and (n<=26) then begin letra := chr(ord(’A’)+n-1); writeln(’A letra n.’, n:1, ’ do alfabeto e’’ ’, letra); end else writeln(’O valor dado nao pertence ao intervalo indicado.’); end. Exerc´ıcio 22. Escreva um programa que: 1. leia dois nu´meros reais e escreva o maior deles; 2. leia treˆs nu´meros reais e os escreva por ordem decrescente do seu valor. Procure fazer o menor nu´mero de perguntas poss´ıvel para ordenar os treˆs nu´meros. Exerc´ıcio 23. Escreva um programa que leia um valor real, x, calcule e escreva o valor da func¸a˜o: f(x) = { 1 x ex se x > 0 e|x| se x ≤ 0 Exerc´ıcio 24. Escreva um programa que, dado x real, calcule: f(x) = { e− ecos x se x ∈ [0, 2pi[ log cosx se x ∈ [−2pi,− 32pi[ ⋃ ]− pi2 , 0[ Exerc´ıcio 25. Escreva um programa que pec¸a ao utilizador os coeficientes a, b e c de um polino´mio ax2 + bx + c, e que verifique (e escreva no monitor) se o polino´mio tem, ou na˜o, ra´ızes reais. Neste caso o programa deve indicar se o polino´mio e´ uma para´bola ou uma recta. Exerc´ıcio 26. Considere a equac¸a˜o da velocidade no instante t (t ≥ 0): v(t) = log |2− 2t+ t2| − e cos2[3(t− 1)] + e−t+1 Elabore um programa que indique se, num instante t0 dado, o objecto se desloca sobrea respectiva trajecto´ria no sentido positivo ou negativo, ou se muda de sentido. 36 Nota: Quando v > 0 o objecto desloca-se no sentido positivo; quando v < 0 o objecto desloca-se no sentido negativo; quando v = 0 o objecto muda de sentido. Exerc´ıcio 27. Considere a seguinte definic¸a˜o de uma func¸a˜o real de duas varia´veis reais: f(x, y) = esin x + ecos y se x ≥ 0 e y ≥ 0 e− sin x − e− cos y se x < 0 e y ≥ 0 loge | sinx+ cos y| se x < 0 e y < 0 loge | cosx− sin y| se x ≥ 0 e y < 0 Fac¸a um programa que devolva o valor de f para x e y, expressos em graus, indicados pelo utilizador. Exerc´ıcio 28. Preveja o resultado e correspondente sa´ıda do seguinte programa. program experiencias (input, output); var m: integer; begin write(’Escreva um inteiro entre 1 e 12: ’); readln(m); if (m>=1) and (m<=12) then case m of 1, 3, 5, 7, 8, 10, 12: writeln(’31 dias.’); 4, 6, 9, 11: writeln(’30 dias’); 2: writeln(’28 ou 29 dias’); end else writeln(’O valor dado nao pertence ao intervalo indicado.’); end. Exerc´ıcio 29. Fac¸a um programa que leia um valor inteiro representando a classificac¸a˜o de um aluno entre 0 e 20 e imprima no ecra˜ a classificac¸a˜o qualitativa correspondente, de acordo com a tabela: Nota 0-9 10-13 14-16 17-20 Classificac¸a˜o Insuficiente Suficiente Bom Muito Bom Exerc´ıcio 30. Pretende-se um programa que converta entre quilo´metros por hora, milhas por hora e no´s. O programa deve pedir ao utilizador o valor e a unidade em que o valor esta´ expresso. Por exemplo, um teste poss´ıvel seria: Qual o valor: 13.7894 Quais as unidades (k = kilometros por hora, m = milhas por hora, n = nos): m Ao que o programa deve responder com o resultado: kilometros por hora = 22.19189 nos = 11.98266 Nota: Recorde que: 1 milha = 1.609344 Km e 1 no´ = 1.852000 Km por hora. Exerc´ıcio 31. Pretende-se um programa que converta entre graus e radianos. O programa deve pedir ao utilizador o valor e as unidades do aˆngulo. Por exemplo: 37 Qual o valor do angulo: 37.894 Quais as unidades (g = graus, r = radianos): g e deve responder com o resultado: Radianos = 0.6613751 O programa deve mostrar uma mensagem de erro se for introduzido um cara´cter de unidades na˜o va´lido. Por exemplo: Qual o valor do angulo: 37.894 Quais as unidades (g = graus, r = radianos): w ERRO: entrada nao valida para unidades: w Nota: Recorde que pi radianos = 180 graus. 2.6.3 Instruc¸o˜es de repetic¸a˜o As instruc¸o˜es de repetic¸a˜o permitem repetir uma instruc¸a˜o simples ou um bloco de instruc¸o˜es (ins- truc¸a˜o composta), e podem ser do tipo while-do, repeat-until, for-downto-do ou for-to-do. Instruc¸o˜es de repetic¸a˜o: while-do A instruc¸a˜o de repetic¸a˜o, ou ciclo, while-do repete uma instruc¸a˜o simples ou composta, enquanto uma condic¸a˜o, representada por uma expressa˜o lo´gica, e´ verdadeira. −→ while −→ expressa˜o lo´gica −→ do −→ instruc¸a˜o −→ O ciclo divide-se em: • cabec¸a: constitu´ıda pelo teste lo´gico, efectuado antes de tudo e repetido em seguida, • corpo: formado pela instruc¸a˜o executada sempre que o resultado do teste e´ verdadeiro. Cada execuc¸a˜o do corpo de um ciclo chama-se uma iterac¸a˜o do ciclo. Se a expressa˜o lo´gica na cabec¸a do ciclo e´ falsa, enta˜o as instruc¸o˜es no corpo do ciclo nunca sa˜o efectuadas. Por exemplo, com este conjunto de instruc¸o˜es i := 1; while i <= 0 do write(i); write(i) o corpo do ciclo nunca e´ executado, portanto apenas e´ impresso o valor 1. Por outro lado, se a expressa˜o lo´gica e´ sempre verdadeira, enta˜o o ciclo nunca pa´ra e estamos perante um ciclo infinito. Existem dois tipos cla´ssicos de ciclos, • os ciclos controlados por um contador: que sa˜o executados um nu´mero conhecido de vezes; • e os ciclos controlados por um sucesso: que terminam quando algo no seu corpo indica que se deve sair. 38 Para exemplificar consideremos o problema de escrever as primeiras dez poteˆncias de 2, que pode ser resolvido com o programa seguinte. program potencias1(output); const lim = 10; var i: integer; begin i := 1; { Inicializacao } while i <= lim do { Ciclo } begin writeln(’2^’, i,’ = ’, exp(i * ln(2))); i := i + 1; { Incremento } end end. Neste caso a varia´vel i funciona como o contador que permite controlar o nu´mero de iterac¸o˜es do ciclo, e portanto o nu´mero de vezes que e´ impressa uma poteˆncia de 2. E´, por isso, importante salientar a inicializac¸a˜o de i, e tambe´m o seu incremento. De facto, omitindo esta actualizac¸a˜o de i, ou seja, escrevendo apenas o ciclo i := 1; while i <= lim do writeln(’2^’, i,’ = ’, exp(i * ln(2))) o valor desta varia´vel seria sempre o inicial, 1, o que originaria um ciclo infinito. Note-se ainda que se pretendermos imprimir tambe´m o valor 20 = 1 a inicializac¸a˜o de i deve ser feita com o valor 0. Apresentamos agora uma versa˜o alternativa a este programa, que permite resolver o mesmo problema usando apenas aritme´tica de inteiros para determinar as poteˆncias a imprimir. program potencias2(output); const lim = 10; var i, potencia: integer; begin i := 1; { Inicializacao } potencia := 2; while i <= lim do { Ciclo } begin writeln(’2^’, i,’ = ’, potencia); i := i + 1; { Incremento } potencia := potencia * 2 end end. Como exemplo de um programa com um ciclo controlado por um sucesso referimos o problema de escrever as poteˆncias de 2 inferiores a 1000. program potencias3(output); const lim = 1000; var i, potencia: integer; begin i := 1; { Inicializacao } potencia := 2; while potencia < lim do { Ciclo } 39 begin writeln(’2^’, i,’ = ’, potencia); i := i + 1; { Incremento } potencia := potencia * 2 end end. Neste caso a condic¸a˜o de paragem depende, na˜o do contador, mas do pro´ximo valor da varia´vel potencia a ser impresso. Alia´s, nesta versa˜o a u´nica utilidade da varia´vel i e´ a de completar a mensagem a imprimir no ecra˜. Instruc¸o˜es de repetic¸a˜o: repeat-until A instruc¸a˜o de repetic¸a˜o repeat-until repete uma instruc¸a˜o simples ou composta, ate´ que uma expressa˜o lo´gica seja verdadeira. −→ repeat −→ instruc¸a˜o −→ until −→ expressa˜o lo´gica −→ As palavras reservadas repeat e until delimitam as instruc¸o˜es que constituem o corpo do ciclo, pelo que neste caso begin e end sa˜o prescind´ıveis. Ao contra´rio do que acontece com o ciclo while-do, no repeat-until o teste lo´gico (a cabec¸a do ciclo) e´ efectuado no final, isto e´, apo´s o bloco de instruc¸o˜es. Uma das consequeˆncias e´ que o ciclo e´ sempre executado pelo menos uma vez. Um ciclo repeat-until pode ser sempre “traduzido” num ciclo while-do, sendo os dois blocos de instruc¸o˜es a seguir equivalentes repeat Instruc¸~oes until cond. paragem aux := true; while aux do begin Instruc¸~oes; aux := cond. paragem end Contudo, em algumas situac¸o˜es e´ torna-se mais simples utilizar um repeat-until do que um while-do. Por exemplo, muitas vezes a condic¸a˜o de paragem so´ fica definida apo´s a primeira passa- gem do ciclo. Nestes casos a implementac¸a˜o de repeat-until e´ directa, enquanto que usar while-do obriga a uma inicializac¸a˜o artificial. Consideremos o problema de ler uma classificac¸a˜o com valores A, B, C, D ou F, e admitamos que so´ pretendemos terminar a leitura quando tiver sido introduzido um valor va´lido, isto e´, um destes caracteres. Uma poss´ıvel soluc¸a˜o consiste em utilizar um ciclo while-do, como em writeln(’De uma nota: ’); readln(nota); while (nota <> ’A’) and (nota <> ’B’) and (nota <> ’C’) and (nota <> ’D’) and (nota <> ’F’) do begin writeln(’De uma nota: ’); readln(nota) end Como referimos, a instruc¸a˜o de leitura que precede o while-do permite definir um valor
Compartilhar