Prova Final 1 de Linguagens de Programaç˜ao - DCC024B

Propaganda
Prova Final
1
de Linguagens de Programação
- DCC024B Ciência da Computação
Nome:
“Eu dou minha palavra de honra que não trapacearei neste exame.”
Número de matrı́cula:
As regras do jogo:
• A prova é sem consulta.
• Quando terminar, não entregue nada além do caderno de provas para o instrutor.
• Quando escrever código, a sintaxe correta é importante.
• Cada estudante tem direito a fazer uma pergunta ao instrutor durante a prova. Traga o caderno de
provas quando vier à mesa do instrutor.
• A prova termina uma hora e quarenta minutos após seu inı́cio.
• Seja honesto e lembre-se: você deu sua palavra de honra.
Alguns conselhos:
• Escreva sempre algo nas questões, a fim de ganhar algum crédito parcial.
• Se não entender a questão, e já tiver gasto sua pergunta, escreva a sua interpretação da questão junto
à resposta.
• A prova não é difı́cil, ela é divertida, então aproveite!
Tabela 1: Pontos acumulados (para uso do instrutor)
Questão 1
1O
Questão 2
Questão 3
Questão 4
não...
1
Questão 5
Questão 6
1. Escreva um predicado eqv(L), em Prolog, que seja verdade quando L for uma lista de átomos, e cada
átomo aparecer o mesmo número de vezes em L. Em outra palavra, se L possui N átomos distintos,
e um deles aparece em L M vezes, então L deve possuir N × M átomos, cada um deles ocorrendo M
vezes em L. Por exemplo:
?- eqv([a, b, c, b, a, c]).
true.
?- eqv([a, b, c]).
true.
?- eqv([a, b, c, b]).
false.
?- eqv([]).
true.
?- eqv([a, a, a, b, b, b, 1, 1, 1]).
true.
2
2. Nesta questão você deverá escrever pelo menos uma caracterı́stica comum entre cada par de linguagens
de programação. Você não pode repetir uma mesma caracterı́stica entre dois pares de linguagens
diferentes. Cada item vale um ponto.
(a) Simula e Java.
(b) Java e Python.
(c) Python e C.
(d) C e Fortran.
(e) Fortran e Cobol.
(f) As primeiras versões de Cobol e as primeiras versões de Lisp.
(g) Lisp e SML.
(h) SML e Algol.
(i) Algol e C++.
(j) C++ e Simula.
3
3. Existem alguns mecanismos de passagem de parâmetros que são considerados não estritos. Um mecanismo de parâmetros não estrito não requer a avaliação dos argumentos passados para uma função
antes da invocação dessa função. Os principais mecanismos não estritos são a passagem por expansão
de macros, a passagem por nome, e a passagem por necessidade.
(a) (5 pontos) Escreva um programa, em uma linguagem hipotética L, cuja sintaxe seja igual à sintaxe
de C, que retornaria diferentes resultados, caso o mecanismo de passagem de parâmetros fosse
a expansão de macros, ou fosse a passagem por nome. Explique qual seria o resultado em cada
caso.
(b) (5 pontos) A passagem por necessidade somente pode ser empregada em linguagens que não
possuem a noção de efeito colateral 2 . Porque tal é o caso?
2 Nem
pense em perguntar, durante a prova, o que vem a ser efeito colateral.
4
4. É fato notório que a linguagem C não possui um coletor de lixo, muito embora esse tipo de ferramenta
incremente em muito a produtividade do desenvolvedor de software. Uma das consequências negativas
que advêm da ausência de um coletor de lixo são os erros de alocação de memória, como os presentes
no programa abaixo, escrito em C:
1 int main() {
2
char *p, *q;
3
p = NULL;
4
printf("%s", p);
5
q = (char*) malloc(100);
6
p = q;
7
free(q);
8
*p = ’x’;
9
free(p);
10
p = (char*) malloc(100);
11
q = p;
12
mystrcat(p, q);
13 }
void mystrcat(char* dst, char* src) {
while (*dst != ’\0’) {
dst++;
}
while (*src != ’\0’) {
*dst = *src;
dst++;
src++;
}
}
(a) (4 pontos) O programa acima possui quatro erros. Liste cada um desses erros, indicando, em
poucas palavras, o que está errado.
•
•
•
•
(b) (2 pontos) Quais dentre os erros acima, não poderiam ser evitados, mesmo que C possuı́sse um
coletor de lixo similar ao que existe em Java?
(c) (4 pontos) A linguagem C não possui um coletor de lixo porque a semântica dessa linguagem torna
a construção de tal ferramenta muito difı́cil. Explique uma das razões por trás de tal dificuldade.
5
5. Nesta questão você irá implementar uma lista circular em Python. Parte do código da lista já está
dado abaixo. Você deve preencher as lacunas.
class EmptyListEx(Exception):
def __init__(self, msg):
self.value = msg
def __str__(self):
return repr(self.value)
class CircList:
def __init__(self):
self.current = None
def empty(self):
return self.current == None
def get(self):
(2 pontos)
(a) O método get retorna o elemento na
posição corrente da lista circular.
O estado da lista não deve ser modificado.
Uma tentativa de retornar um elemento de
uma lista vazia dispara EmptyListEx.
def move(self):
(2 pontos)
(b) O método move modifica o estado da lista,
alterando seu ponteiro corrente para a próxima
posição, considerando a circularidade da lista.
Uma tentativa de mover o elemento corrente
em uma lista vazia dispara EmptyListEx.
def add(self, element):
(3 pontos)
(c) O método add insere element uma posição
antes do elemento corrente da lista. O elemento
corrente passa então a ser element. Em
outras palavras, c.get(c.add("oi"))
deve retornar o próprio elemento "oi".
Esse método não dispara exceções.
def find(self, element):
(3 pontos)
(d) O método find posiciona o ponteiro corrente
sobre a primeira ocorrência de element dentro
da lista circular. Se a lista estiver vazia, nada
acontece.
6
6. Ao contrário de Python, a linguagem Java provê exceções verificáveis estaticamente. Estas exceções
precisam ser tratadas explicitamente pelo desenvolvedor. Por exemplo, o método Java abaixo não
compilaria caso removêssemos as cláusulas de tratamento de erro:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public static void fileReader(final String fileName) {
try {
Scanner s = new Scanner(new File(fileName));
// ... read the file here ...
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
(a) (2 pontos) O que distingue uma exceção verificável estaticamente de uma exceção que não precisa
ser verificada?
(b) (3 pontos) Cite uma vantagem desta abordagem adotada por Java
(c) (3 pontos) Java é a única linguagem muito popular que adota exceções verificáveis estaticamente.
Obviamente existem desvantagens nesta abordagem, pois linguagens posteriores à Java não a
seguiram. Cite uma desvantagem das exceções verificadas estaticamente.
(d) Exceções verificáveis estaticamente são uma forma de documentação que o compilador verifica.
Cite outras duas formas de documentação que o compilador javac consegue verificar.
7
Download