Resolução do Exame de 1ª Época de 2003

Propaganda
2605 - Linguagens Imperativas e
Orientadas por Objectos
Ano Lectivo 2002/2003
Relatório do Exame Nº 1
Este relatório reproduz o texto do exame na íntegra, adicionado das resposta em itálico.
Instruções
Este exame têm três grupos, com a cotações relativas indicadas entre parêntesis. Cada grupo
têm uma ou mais questões. As questões são numeradas a partir de 1 até ao fim do teste.
Responda a cada questão no espaço imediatamente a seguir ao respectivo enunciado. Se
precisar de mais espaço utilize a última página, identificando a questão. Ao escrever código,
utilize letras separadas (não cursivas), seja cuidadoso com os símbolos e.g. distinga bem o
hífen (-) da sublinha (_), e espaceje bem os elementos lexicais entre si. Distinga bem entre
código e texto normal, se a sua resposta contiver ambos. Dê respostas concisas e claras. Pode
usar abreviaturas para as palavras-chave muito frequentes, e.g. proc (procedure), func
(function), ret (return), alistando-as no fim. Não aborde os vigilantes sobre o texto do
exame. Se detectar alguma ambiguidade ou gralha, resolva-a individualmente, incluindo essa
resolução na sua resposta.
I. Ada (50%)
1. Escreva, em Ada, o programa Olá Mundo. (O programa Olá Mundo é um programa cujo
comportamento se resume a escrever "Olá, mundo!" na saída de dados padrão.)
with Ada.Text_IO;
procedure Olá_Mundo is
begin
Ada.Text_IO.Put_Line ("Olá, mundo!");
end;
2.
Defina a classe de derivação
Pessoa
:
:..Amigo
:
:..Colega
tal que:



toda pessoa tem um nome
uma pessoa concreta é ou um amigo ou um colega
os amigos são saudados por "ôi" e os colegas por "bom dia"
1
Usando class wide programming, defina uma colecção de pessoas, contendo pelo menos um
amigo e um colega, e saúde todas as pessoas da colecção. Escreva o resultado esperado do
programa.
package Pessoas is
type String_Ptr is access String;
type Pessoa is abstract tagged
record
Nome : String_Ptr;
end record;
procedure Saudar (X : Pessoa) is abstract;
type Pessoa_Ptr is access Pessoa'Class;
type Amigo is new Pessoa with null record;
procedure Saudar (X : Amigo);
type Colega is new Pessoa with null record;
procedure Saudar (X : Colega);
end;
----with Ada.Text_IO; use Ada.Text_IO;
package body Pessoas is
procedure Saudar (X : Amigo) is
begin
Put_Line ("ôi, " & X.Nome.all);
end;
procedure Saudar (X : Colega) is
begin
Put_Line ("bom dia, " & X.Nome.all);
end;
end;
----with Pessoas; use Pessoas;
procedure Saudar_Pessoas is
Pessoas_Conhecidas : array (1 .. 2) of Pessoa_Ptr :=
(1 => new Amigo' (Nome => new String' ("Zé"
)),
2 => new Colega' (Nome => new String' ("Sr. Fonseca")));
begin
for I in Pessoas_Conhecidas'Range loop
Saudar (Pessoas_Conhecidas (I).all);
end loop;
2
end;
Resultado esperado:
ôi, Zé
bom dia, Sr. Fonseca
3. Especifique um pacote genérico que fornece listas. Uma lista é uma sequência variável de
elementos. Os elementos podem ser adicionados ao princípio ou ao fim da lista, ou
imediatamente antes ou depois de qualquer elemento existente. Qualquer elemento pode
ser removido. Tem que haver um meio de aceder a todos os elementos. Escreva um
exemplo de utilização do pacote, e o resultado esperado.
generic
type Elemento is private;
package Listas is
type Lista is private;
type Posição is private;
function Primeiro (L : Lista) return Posição;
function Último
(L : Lista) return Posição;
function Seguinte (P : Posição) return Posição;
function Anterior (P : Posição) return Posição;
function Valor_Elementar (P : Posição) return Elemento;
procedure Adicionar_Antes (L : in out Lista ; P : Posição; E :
Elemento);
procedure Adicionar_Depois (L : in out Lista ; P : Posição; E :
Elemento);
procedure Remover (L : in out Lista ; Q : Posição);
Posição_Nula_Mas_Lista_Não_Vazia : exception;
private
type Lista is record
Primeiro : Posição;
Último : Posição;
end record;
type Nó is record
Carga : Elemento;
Seguinte : Posição;
Anterior : Posição;
end record;
type Posição is access Nó;
end;
----with Ada.Text_IO;
with Listas;
procedure Listest is
package Listas_C is new Listas (Character);
use Listas_C;
L : Lista;
procedure Ver_Lista is
use Ada.Text_IO;
I : Posição := Primeiro (L);
begin
Put ('[');
loop
Put (Valor_Elementar (I));
I := Seguinte (I);
3
end loop;
exception
when others =>
Put_Line ("]");
end;
begin
Ver_Lista;
Adicionar_Depois (L, Último (L), 'a'); Ver_Lista;
Adicionar_Depois (L, Último (L), 'b'); Ver_Lista;
Adicionar_Depois (L, Último (L), 'c'); Ver_Lista;
Remover (L, Último (L)); Ver_Lista;
Remover (L, Último (L)); Ver_Lista;
Remover (L, Último (L)); Ver_Lista;
end;
Resultado esperado de Listest:
[]
[a]
[ab]
[abc]
[ab]
[a]
[]
II. Smalltalk (20%)
4.
Escreva o programa Olá Mundo em Smalltalk. (Pode usar o Transcript como saída
padrão.)
Transcript show: 'Olá, mundo!'
5. O protocolo da class Object (o topo da hierarquia de classes do sistema Smalltalk) inclui
as seguintes mensagens:
isMemberOf: aClass
Responde o valor booleano do facto do receptor ser uma instância da classe
especificada.
class
Responde a classe do receptor.
Implemente o método isMemberOf:, utilizando class.
isMemberOf: aClass
"Responde o valor booleano do facto do receptor ser uma instância da
classe especificada."
^ self class == aClass
6. Acrescentámos ao protocolo da classe Float a mensagem hipotenusa: outroCateto com
o comportamento esperado. Implemente o respectivo método.
hipotenusa: outroCateto
"Responde
a
hipotenusa
especificado."
correspondente
4
ao
receptor
e
ao
cateto
^ ((self ** 2) + (outroCateto ** 2)) sqrt
7. Descreva o resultado da avaliação das seguintes expressões em Smalltalk:
2 * 3 + 6
(2 * 3) + 6
2 * (3 + 6)
2 + 3 * 6
(2 + 3) * 6
2 + (3 * 6)
->
->
->
->
->
->
12
12
18
30
30
20
III. Linguagem à escolha (30%)
8. Considere a pequena linguagem imperativa Li dedicada exclusivamente a números
inteiros. Li tem literais, três variáveis prédeclaradas A, B, C, e as operações de afectação
(assignment), soma, multiplicação e entrada/saída de dados. Escolha Ada ou Smalltalk,
e conceba uma maneira de representar e executar programas em Ic. Escreva um programa
de teste, e o resultado esperado. Use técnicas de orientação por objectos, ou justifique
porque não.
Escolho Ada. O pacote Lilib fornece meios de representação e execução de programas Li:
package Lilib is
type Variable is (A,B,C);
type Expression is private;
function Literal (Value : Integer) return Expression;
function Name (Name : Variable) return Expression;
function "+" (L, R : Expression) return Expression;
function "*" (L, R : Expression) return Expression;
type Statement is private;
function Assign (Name : Variable ; X : Expression) return Statement;
function Write (X : Expression) return Statement;
function Read (Name : Variable) return Statement;
type Program is array (Positive range <>) of Statement;
procedure Execute (P : Program);
private
type Expression_Root is abstract tagged null record;
function Value (X : Expression_Root) return Integer is abstract;
type Expression is access all Expression_Root'Class;
type Statement_Root is abstract tagged null record;
procedure Execute (S : Statement_Root) is abstract;
type Statement is access all Statement_Root'Class;
end;
A utilização deste pacote é exemplificada pelo seguinte programa de teste:
with Lilib; use Lilib;
procedure Litest is
5
begin
Execute
((
Write (Literal (1)),
Write (Literal (2)),
Assign (A, Literal (3)),
Write (Name (A)),
Assign (B, Name (A) + Literal (4)),
Write (Name (B)),
Write (Literal (2) * Literal (2))
));
end;
Resultado esperado: 1 2 3 7 4.
Implementação do pacote Lilib:
with Ada.Streams.Stream_IO;
with Ada.Text_IO;
with GNAT.IO_Aux;
package body Lilib is
--> LITERAL EXPRESSION
type Literal_Expression is new Expression_Root with
record
Value : Integer;
end record;
function Value (X : Literal_Expression) return Integer;
--> NAME EXPRESSION
type Name_Expression is new Expression_Root with
record
Name : Variable;
end record;
function Value (X : Name_Expression) return Integer;
--> SUM EXPRESSION
type Sum_Expression is new Expression_Root with
record
Left, Right : Expression;
end record;
function Value (X : Sum_Expression) return Integer;
--> PRODUCT EXPRESSION
type Product_Expression is new Expression_Root with
record
Left, Right : Expression;
end record;
function Value (X : Product_Expression) return Integer;
--> ASSIGN STATEMENT
6
type Assign_Statement is new Statement_Root with
record
Name : Variable;
X : Expression;
end record;
procedure Execute (S : Assign_Statement);
--> WRITE STATEMENT
type Write_Statement is new Statement_Root with
record
X : Expression;
end record;
procedure Execute (S : Write_Statement);
--> READ STATEMENT
type Read_Statement is new Statement_Root with
record
Name : Variable;
end record;
procedure Execute (S : Read_Statement);
--> EXPRESSION METHOD BODIES
Store : array (Variable) of Integer;
function Value (X : Name_Expression) return Integer is
begin
return Store (X.Name);
end;
function Value (X : Literal_Expression) return Integer is
begin
return X.Value;
end;
function Value (X : Sum_Expression) return Integer is
begin
return Value (X.Left.all) + Value (X.Right.all);
end;
function Value (X : Product_Expression) return Integer is
begin
return Value (X.Left.all) * Value (X.Right.all);
end;
--> EXPRESSION CONSTRUCTOR BODIES
function Name (Name : Variable) return Expression is
begin
return new Name_Expression' (Name => Name);
end;
function Literal (Value : Integer) return Expression is
begin
return new Literal_Expression' (Value => Value);
7
end;
function "+" (L, R : Expression) return Expression is
begin
return new Sum_Expression' (L, R);
end;
function "*" (L, R : Expression) return Expression is
begin
return new Product_Expression' (L, R);
end;
--> STATEMENT CONSTRUCTOR BODIES
function Assign (Name : Variable ; X : Expression) return Statement is
begin
return new Assign_Statement' (Name, X);
end;
function Write (X : Expression) return Statement is
begin
return new Write_Statement' (X => X);
end;
function Read (Name : Variable) return Statement is
begin
return new Read_Statement' (Name => Name);
end;
--> STATEMENT METHOD BODIES
procedure Execute (S : Assign_Statement) is
begin
Store (S.Name) := Value (S.X.all);
end;
procedure Execute (S : Write_Statement) is
begin
Ada.Text_IO.Put (Integer'Image (Value (S.X.all)));
end;
procedure Execute (S : Read_Statement) is
begin
Store (S.Name) := Integer'Value (GNAT.IO_Aux.Get_Line);
end;
--> PROGRAM METHOD BODY
procedure Execute (P : Program) is
begin
for I in P'Range loop
Execute (P (I).all);
end loop;
end;
end;
8
Download