INF1018 - Software Básico - 2011.2

Primeiro Trabalho

Gravação compactada

O objetivo do trabalho é implementar, na linguagem C, uma função (gravacomp) que escreve um array de structs em um arquivo binário de forma compacta (isto é, sem padding) e uma função (dump) que permite visualizar um arquivo gerado por gravacomp.

Leia com atenção o enunciado do trabalho e as instruções para a entrega. Em caso de dúvidas, não invente. Pergunte!


Função gravacomp:

int gravacomp (int nstructs, void* valores, char *campos, FILE *arquivo); 
A função gravacomp recebe como argumentos: A função deverá retornar 0 em caso de sucesso, e -1 em caso de erro.

A string campos representa, na ordem, o tipo de cada campo das structs, de acordo com o código a seguir:

    'c' - char
    's' - short int
    'i' - int 
    'p' - ponteiro

Como exemplo, dada a declaração:

  struct s {
    short s1;
    int i1;
    char c1;
    char *p1;
    int i2;
    short s2;
    char c2;
  };
struct s exemplo[10];
a string campos correspondente é "sicpisc".

Assumindo que o descritor do arquivo de saída está armazenado em uma variável arq, do tipo FILE *, a chamada para a gravação do array exemplo seria:

   res = gravacomp(10, &exemplo, "sicpisc", arq);


Formato do arquivo gerado:

Os primeiros bytes do arquivo formam o cabeçalho, com informações sobre os dados armazenados. A seguir vem um sequência de bytes contendo os dados propriamente ditos.

O primeiro byte do cabeçalho indica o número de structs armazenadas no arquivo, como um unsigned char. A seguir aparecem os descritores de campos dos structs, cada um com 3 bits. Cada descritor é codificado da seguinte forma:

    001 - char
    010 - short int
    100 - int 
    101 - ponteiro
O padrão 000 marca o final da lista de campos. A porção não utilizada do último byte de cabeçalho (se houver) deve ser ignorada (ou seja, o inicio dos dados propriamente ditos deve estar alinhado no próximo byte do arquivo).

Após o cabeçalho aparecem os bytes com os dados do array de structs, armazenados no arquivo em big-endian. Não devem ser escritos no arquivo os bytes relativos a padding.

Voltando ao caso do array exemplo, o início do arquivo ficaria assim:

| 0000 1010 | /* há 10 structs neste arquivo */
| 0101 0000 | /* aqui começa a descrição dos campos */
| 1101 1000 | 
| 1000 1000 |
| xxxx xxxx | /* aqui começam os dados das 10 structs */

Nesse exemplo, na memória de um IA-32 executando Linux, cada struct ocuparia 24 bytes. Ao ser armazenada em arquivo por gravacomp, essa mesma struct ocuparia 18 bytes.


Função dump:

void dump (FILE *arquivo); 

A função dump permite a visualização, na saída padrão, de um arquivo criado por gravacomp. Essa saída pode ser gerada, por exemplo, através de chamadas a printf.

O único argumento de dump é o descritor de um arquivo aberto para leitura, em modo binário. Não é necessário considerar erros na leitura desse arquivo.

A saída da função dump deve ser a seguinte:

Como exemplo, para o mesmo arquivo discutido acima, a saída de dump seria:
10
sicpisc
xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
xx xx
xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
xx xx
xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
xx xx
xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
xx xx
xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
xx xx
xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
xx xx
xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
xx xx
xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
xx xx
xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
xx xx
xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
xx xx
(onde os "xx" correspondem aos valores (em hexa) dos bytes armazenados)


Implementação e Execução

Você deve criar um arquivo fonte chamado compacta.c contendo as duas funções descritas acima (gravacomp e dump) e funções auxiliares, se for o caso. Esse arquivo não deve conter uma função main!

Crie também um arquivo compacta.h , que deve conter apenas os protótipos (cabeçalhos) das funções gravacomp e dump.

Para testar seu programa, crie um outro arquivo, teste.c, contendo a função main. Crie seu programa executável teste com a linha:

gcc -Wall -m32 -o teste compacta.c teste.c

Tanto o arquivo compacta.c como teste.c devem conter a linha:

#include <compacta.h>


Entrega

Devem ser entregues três arquivos:
  1. o arquivo compacta.c
  2. o arquivo teste.c
  3. um arquivo texto, chamado relatorio, descrevendo os testes realizados, o que está funcionando e, eventualmente, o que não está funcionando. Mostre exemplos de estruturas testadas (casos de sucesso e insucesso, se houver)!

Coloque no início dos arquivos fonte, como comentário, os nomes dos integrantes do grupo, da seguinte forma:

  /* Nome_do_Aluno1 Matricula Turma */
  /* Nome_do_Aluno2 Matricula Turma */
Coloque também no relatório o nome dos integrantes do grupo.

O trabalho deve ser enviado por email para o professor da turma, com subject/assunto "Trabalho 1 - Software Basico". Indique claramente os integrantes do grupo no corpo do email e inclua, como anexo, os três arquivos pedidos (compacta.c, teste.c e relatorio).


Prazo

O trabalho deve ser entregue até a meia-noite do dia 26/9.


Observações