->Come si vedrà a breve, in C capita molto spesso di accedere ai campi di una struttura tramite un puntatore a tale struttura. Allora, per rendere più compatto e leggibile il codice, il linguaggio mette a disposizione una “scorciatoia”: l’operatore binario infisso ->. Esso deve avere come operando sinistro un puntatore pt a una struttura e come operando destro un’etichetta campo di un campo di tale struttura. Dati tali operandi, *pt -> campo* è esattamente equivalente a (*pt).campo: si deferenzia il puntatore pt e si seleziona il campo campo della struttura puntata, che può così essere letto e/o modificato.
La pila, o stack, è una delle più semplici e importanti strutture dati. Le principali operazioni su una pila sono:
init_stack: crea la struttura dati in memoriapush: inserisce un nuovo elementopop: elimina l’elemento in cimatop: legge l’elemento in cimais_empty: indica se la pila è attualmenet vuotaCi sono vari modi di implementare una struttura che supporti queste operazioni. Adesso, come esempi di applicazioni della memoria dinamica, si vedranno due possibili implementazini: una basata su un vettore allocato dinamicamente e una basata su una lista concatenata.
Una pila basata su un vettore allocato dinamicamente può essere rappresentata dalla seguente struttura stack:
typedef int ITEM;
struct stack {
ITEM *array;
int max_size;
int top;
};
typedef struct stack STACK;
typedef per assegnare a esso il nome astratto ITEM: così, per cambiare il tipo degli elementi è sufficiente modificare la typedef.stack servono a tenere traccia di tutte le informazioni necessarie per la gestione della pila:
array è un puntatore al vettore di ITEM allocato dinamicamente che conterrà gli elementi della pilamax_size indica la dimensione del vettore allocato, ovvero il numero massimo di elementi che la pila può conteneretop è l’indice della prima posizione libera del vettorestack non corrisponde di per sè a un tipo, perchè è solo l’etichetta di una struttura: il nome del tipo corrispondente è struct stack. Volendo evitare di scrivere struct stack ogni volta, si usa una typedef per associare a tale tipo un nome più breve: STACk.Adesso verranno mostrate le implementazioni delle varie operazioni sulla pila. Si noti che, per semplicità, verranno omessi alcuni dettagli, come ad esempio la gestione degli errori e la deallocazione della memoria allocata, che sarebbero importanti in un’implementazione “reale”, destinata all’uso pratico, ma non riguardano strettamente la logica di gestione della struttura dati
init_stackLa funzione init_stack crea dinamicamente una pila in grado di contenere al massimo il numero di elementi passato come argomenti. La pila creata è inizialmente vuota.
STACK *init_stack(int n) {
STACK *tmp = (STACK *)malloc(sizeof(STACK));
if (tmp == NULL) {
// Gestione dell'errore...
return NULL;
}
tmp->array = (ITEM *)calloc(n, sizeof(ITEM));
if (tmp->array == NULL) {
// Gestione dell'errore...
return NULL;
}
tmp->max_size = n;
tmp->top = 0;
return tmp;
}