#include "naive_sequence_of_longs.h"
sequence_of_longs.c – Implementação das sucessões de longsequence_of_longsPara uma explicação mais pormenorizada das várias partes deste ficheiro, e da
implementação das várias rotinas, consultar a explicação do correspondente
ficheiro sequence_of_longs.c. Neste ficheiro
explica-se apenas aquilo que é específico desta implementação ingénua do TAD
sucessão de long.
Este ficheiro de implementação contém a implementação do módulo físico
naive_sequence_of_longs. A interface deste módulo encontra-se no ficheiro
de cabeçalho ou de interface
naive_sequence_of_longs.h.
#include "naive_sequence_of_longs.h"
#include <stdio.h>
#include <stdlib.h>
struct naive_sequence_of_longEsta estrutura contém dois campos ou atributos:
terms – Um ponteiro para o array dinâmico que contém os termos da
sucessão.
length – Inteiro guardando o comprimento actual da sucessão, i.e.,
o seu número de termos. Note que o comprimento da sucessão é sempre
igual ao comprimento do array que guarda os termos.
struct naive_sequence_of_longs {
long *terms;
int length;
};
void NSEQL_print(struct naive_sequence_of_longs *sl)
{
putchar('{');
for (int i = 0; i != sl->length; i++) {
if (i != 0)
printf(", ");
printf("%ld", sl->terms[i]);
}
putchar('}');
}
void NSEQL_println(struct naive_sequence_of_longs *sl)
{
NSEQL_print(sl);
putchar('\n');
}
struct naive_sequence_of_longs *NSEQL_new(void)
{
Reservamos primeiro espaço para uma nova struct sequence_of_longs
usando a rotina malloc(). Obtemos a quantidade de unidades de
memória a reservar usando o operador sizeof. Guardamos o endereço
dessa nova variável dinâmica no ponteiro sl, através do qual se
passará a manipular a nova sucessão de long. No final do construtor
este ponteiro será devolvido.
struct naive_sequence_of_longs *sl =
malloc(sizeof(struct naive_sequence_of_longs));
De seguida inicializamos os campos ou atributos da rotina com valores
apropriados para uma sucessão vazia. O comprimento de uma sucessão
vazia é naturalmente 0. Uma vez que não é possível ter um ponteiro
válido para um array dinâmico com 0 itens, inicializa-se o ponteiro
para o primeiro item desse array com o valor NULL.
sl->length = 0;
sl->terms = NULL;
Terminada a construção da nova sucessão, há que devolver o seu
endereço (ou ponteiro), guardado na variável sl.
return sl;
}
int NSEQL_length(struct naive_sequence_of_longs *sl)
{
return sl->length;
}
void NSEQL_add(struct naive_sequence_of_longs *sl, long new_term)
{
Uma vez que o array dinâmico tem sempre a sua capacidade esgotada,
adicionar um novo termo à sucessão implica sempre redimensionar esse
array. Para aumentar a capacidade, usamos a rotina realloc() para
reservar um novo array dinâmico com capacidade para mais um termo
e incluindo todos os termos que já constam na sucessão. É este
último requisito que nos leva a usar a rotina realloc(), e não a
rotina malloc(). A rotina realloc(), se precisar de reservar nova
memória, i.e., se não conseguir simplesmente estender o array
existente, copiará automaticamente os termos da memória original. É
por isso que o primeiro argumento passado a realloc() é um ponteiro
para o array original.
sl->terms = realloc(sl->terms, (sl->length + 1) * sizeof(long));
Finalmente, guardamos o novo termo new_term no local apropriado do
array, que neste ponto já tem certamente (hmmmm... será?)
capacidade suficiente, i.e., na posição sl->length. Depois,
incrementamos o comprimento da sucessão.
sl->terms[sl->length++] = new_term;
}
long NSEQL_term(struct naive_sequence_of_longs *sl, int index)
{
return sl->terms[index];
}