LEETC - Programação Imperativa em C e C++

Propaganda
Instituto Superior de Engenharia de Lisboa
LEETC - Programação Imperativa em C e C++
Semestre letivo 2013/14-2
Teste de 1.ª data
Nota importante: Valoriza-se a escrita de código que inclua comentários esclarecedores da implementação seguida
e que contenha indentação legível.
1. [3 valores] Considere a macro M:
#define M(varname, index) ( ( (unsigned char*) & varname )[index] )
a) [1] Descreva os resultados apresentados em standard output, na execução do troço de programa seguinte, tendo
em conta as características da plataforma IA-32. Justifique.
int a = 0x12345678;
printf( "%x %x\n", M(a,0), M(a,3) );
b) [1] Suponha a existência de uma variável com o nome b, cujo tipo pode ser básico ou struct. Escreva um troço
de programa que utilize a macro M para apresentar, em standard output, o conteúdo da memória ocupada pela
variável b.
c) [1] Admitindo que pretende escrever programas com portabilidade para plataformas little-endian (armazena o
byte de menor peso no endereço mais baixo) ou big-endian (ordem inversa), escreva a macro
SET_IF_LITTLE_ENDIAN(res)
que recebe no parâmetro res o nome de uma variável com tipo inteiro, afetando-a com 1, se a plataforma de
execução for little-endian, ou 0, se for big-endian.
2. [12 valores] Interprete o excerto de programa seguinte, destinado a gerir vetores genéricos. Cada vetor é formado por
um descritor e um array para os dados, ambos alojados dinamicamente. O array tem crescimento automático, pela
colocação de dados.
typedef struct vector {
int buffer_size; /* espaço alojado, em número de elementos */
int data_size;
/* número de elementos de dados armazenados */
int el_size;
/* dimensão do elemento em bytes */
int (*compare)( void * elem1, void * elem2 ); /* função de comparação,
retorna: <0, elem1 < elem2; 0, elem1 == elem2; >0, elem1 > elem2. */
char * buffer;
/* ponteiro para o alojamento do array */
} Vector;
Vector * vector_create( int buffer_size, int el_size,
int (*compare)( void * elem1, void * elem2 ) ){
Vector init = { buffer_size, 0, el_size, compare,
malloc( buffer_size* el_size ) };
Vector * vec = malloc( sizeof *vec );
*vec = init;
return vec;
}
void vector_put( Vector * vec, void * elem ){
if( vec->data_size == vec->buffer_size )
vec->buffer = realloc( vec->buffer, ++vec->buffer_size * vec->el_size );
memcpy( vec->buffer + vec->el_size * vec->data_size++, elem, vec->el_size );
}
void * vector_search( Vector * vec, void * key ){
int i; char * p;
for( i = vec->data_size, p = vec->buffer ; i != 0 ; --i, p += vec->el_size )
if( vec->compare( p, key ) == 0 )
return p;
return NULL;
}
PICC, 2013/14-2
Teste, 1.ª data
Por exemplo, o troço de programa seguinte cria um vetor de elementos do tipo int e coloca os valores 10, 30 e 20.
int x = 10, y = 30, z = 20, k1 = 30, k2 = 40, *p1, *p2;
Vector * v = vector_create( 1, sizeof(int), compare_int );
vector_put( v, &x );
vector_put( v, &y );
vector_put( v, &z );
p1 = vector_search( v, &k1 );
p2 = vector_search( v, &k2 );
A pesquisa do valor 30 obtém um ponteiro válido e a pesquisa do valor 40 obtém um ponteiro com o valor NULL.
a) [1] Escreva a função compare_int, para associar ao vetor do exemplo anterior, passando no parâmetro
compare da função vector_create. A função compare_int recebe o endereço de dois elementos do
tipo int e devolve um valor negativo, zero ou superior a zero se, respetivamente, o primeiro elemento for
inferior, igual ou superior ao segundo.
b) [4] Escreva uma versão em assembly IA-32 da função vector_search.
c) [1] Modifique a função vector_put de modo a deixar os dados ordenados crescentemente, após cada
colocação. Propõe-se que use a função qsort, da biblioteca normalizada, que realiza a ordenação genérica de
arrays, recebendo o endereço base do array, o número de elementos, a dimensão do elemento e o endereço de
uma função de comparação para determinar a ordem relativa dos elementos.
void qsort( void* base, size_t num, size_t size,
int (*cmp_func)( const void*, const void* ) );
d) [1] Indique, justificando, se é possível melhorar a eficiência da função de pesquisa vector_search, tendo em
conta o armazenamento ordenado resultante da modificação especificada na alínea c).
e) [2,5] Admitindo que se pretende organizar o código para gestão de vetores genéricos num módulo de programa,
descreva resumidamente o que se deve colocar no ficheiro de programa, vector.c, e escreva completamente o
ficheiro de inclusão, vector.h.
f) [1] Supondo que escreveu o programa de aplicação na função main de um módulo com o nome demo.c,
escreva o makefile para gerar o executável demo usando a organização especificada na alínea e).
g) [1,5] Considere que o programa demo.c da alínea f) contém o exemplo de aplicação apresentado, mas falta
criar a função compare_int. Qual é a fase que falha no processo de produção do executável (compilação, de
que módulo, ou ligação)? Qual é o comando, do makefile anterior, que falha? Usando a ferramenta nm, em
que ficheiro encontraria a referência ao símbolo compare_int e como seria classificado?
3. [2 valores] Considere uma árvore binária de pesquisa, cujos nós foram definidos com o tipo Tnode.
typedef struct tnode{ struct tnode * left; struct tnode * right;
void * data; } Tnode;
Escreva a função Tinvert_order que inverte o critério de ordenação usado na árvore (crescente para
decrescente ou vice-versa). No estado inicial a árvore já está ordenada por um critério; deve realizar apenas a
troca de ligações necessária para invertê-lo. Não se pretende modificar o estado de balanceamento.
4. [3 valores] Considere uma lista simplesmente ligada, cujos nós foram definidos com o tipo Lnode.
typedef struct lnode{ struct lnode * next; int data; } Lnode;
Pretende-se criar uma lista ordenada crescente com os valores lidos de um ficheiro de texto, “dados.txt”. O
ficheiro contém uma sequência de valores numéricos inteiros, expressos em ASCII com notação decimal, com
ordenação predominantemente crescente – a maioria dos valores estão por ordem, mas alguns poderão não estar.
A criação da lista com esta especificação é feita pela função
Lnode * Lcreate_from_file( FILE * f );
que retorna o endereço do primeiro elemento da lista construída.
a)
[0,5] Escreva um troço de programa que abra o ficheiro e invoque a função Lcreate_from_file.
b) [2,5] Escreva a função Lcreate_from_file, assegurando a reordenação dos elementos fora de ordem.
Valoriza-se a eficiência, tirando partido da ordem predominante dos dados no ficheiro. Note que se percorrer a
lista na totalidade, ou quase, por cada elemento a inserir, a eficiência é relativamente baixa.
ISEL, 2014.07.07
Download