Ejemplo n.º 1
0
int main(void)
{
	struct sequence_of_longs sequence;
	SEQL_initialize(&sequence);

	for (long i = 0L; i != 10L; i++)
		SEQL_add(&sequence, i);

	printf("The length is: %d\n", SEQL_length(&sequence));

	printf("The sequence is: ");
	SEQL_println(&sequence);

	printf("The items are:");
	for (int i = 0; i != SEQL_length(&sequence); i++)
		printf(" %ld", SEQL_item(&sequence, i));
	putchar('\n');

	return EXIT_SUCCESS;
}
Ejemplo n.º 2
0
// #### Definição
long recursive_fibonacci_using_ADT(int n)
{
	assert(n >= 0);
	assert(n <= MAXIMUM_TERM_FITTING_A_LONG);

	// Em vez de se usar um _array_ de `long` como memória para os termos já
	// calculados da sucessão de Fibonacci, bem como um inteiro indicando a
	// quantidade de termos memorizados, recorremos aqui ao TAD sucessão de
	// `long`, representado pela estrutura `struct sequence_of_longs`. No
	// caso particular da sequência se Fibonacci, a utilização deste TAD não
	// traz grandes vantagens face à utilização de um _array_, dada a
	// pequena quantidade de termos da sucessão representáveis no tipo
	// _long_. No entanto, é um bom exercício recorrer aqui ao TAD,
	// exercício que nos pode ser útil noutros casos em que o
	// dimensionamento _a priori_ do _array_ não seja tão fácil.
	//
	// Tal como definido o TAD, o código cliente só pode trabalhar com as
	// sucessões através de ponteiros. Assim, precisamos de definir uma
	// variável local _estática_ (de modo a que o seu valor persiste entre
	// invocações da função `recursive_fibonacci_using_ADT`). Dadas as
	// restrições do C, não podemos usar o construtor `SEQL_new()`
	// directamente na inicialização, que tem de ser feita usando uma
	// _expressão constante_. Assim, optámos por inicializar o ponteiro `F`
	// com o valor especial `NULL`.
	static struct sequence_of_longs *F = NULL;

	// Dada a inicialização do ponteiro com `NULL`, podemos agora detectar o
	// seu valor inicial `NULL` para lhe atribuir o endereço de uma nova
	// estrutura `struct sequence_of_longs` construída de forma dinâmica
	// através do construtor `SEQL_new()`. Este código é executado sempre
	// que a função é invocada, o que é uma infelicidade, mas não há forma
	// de o evitar, dado que não é possível inicializar o ponteiro `F` para
	// a sucessão de `long` com o valor devolvido pela função `SEQL_new()`.
	//
	// Outro problema associado às limitações do C é o da libertação de
	// memória. O C não fornece nenhum mecanismo para executar código no
	// contexto das variáveis locais estáticas no final do programa de modo
	// a podermos «arrumar a casa», ou seja, libertar recursos que lhes
	// estejam associados. Neste caso os recursos são apenas duas variáveis
	// dinâmicas: (a) a `struct sequence_of_long` apontada por `F` e, embora
	// como clientes não o devêssemos precisar de o saber, (b) o _array_
	// dinâmico usado internamente pelo TAD para guardar os termos. Como
	// toda a memória dinâmica associada ao programa em execução é libertada
	// durante a sua terminação, a nossa violação do princípio de que quem
	// reserva memória explicitamente a deve também libertar explicitamente
	// não é dramática.
	if (F == NULL)
		F = SEQL_new();

	// Se o termo já constar na sucessão de `long` contendo os termos da
	// sucessão de Fibonacci já calculados, então limitamo-nos a devolvê-lo.
	if (n < SEQL_length(F))
		return SEQL_term(F, n);

	// Se o termo não está ainda calculado, há que fazê-lo. Uma vez que,
	// depois de o calcular, teremos de o adicionar à memória e devolver,
	// definimos uma variável `F_n` para guardar o valor calculado. Uma vez
	// que o valor usado para inicializar esta variável depende do valor de
	// `n`, usamos o operador `?:` do C para discriminar entre as três
	// diferentes formas de inicialização, evitando ter de recorrer a uma
	// definição sem inicialização seguida de duas instruções de selecção
	// encadeadas:
	//
	// ```C
	// long F_n;
	// if (n == 0)
	//         F_n = 0L;
	// else if (n == 1)
	//         F_n = 1L;
	// else
	//         F_n = recursive_fibonacci_using_ADT(n - 2) +
	//               recursive_fibonacci_using_ADT(n - 1);
	// ```
	long F_n = n == 0 ? 0L : n == 1 ? 1L :
		recursive_fibonacci_using_ADT(n - 2) +
		recursive_fibonacci_using_ADT(n - 1);

	// Agora que já temos o valor de `F_n` calculado, devemos guardá-lo em
	// memória, na nossa sucessão de `long`, de modo a não precisar de ser
	// calculado de novo.
	SEQL_add(F, F_n);

	// Finalmente, devolvemos o valor calculado.
	return F_n;
}