Pila in C

Pila in C

In questa lezione svilupperemo un semplice esercizio sull’uso della pila in C.

Creiamo dunque un programma per la gestione di una pila che permette di inserire dei valori, eliminarli, stamparli e cancellarli tutti in una volta.

Serviranno dunque le funzioni:

Push per l’inseriemento dei dati;

Pop per l’estrazione dei dati;

Clear per cancellare tutti i dati della pila;

Print per stampare tutti i dati dall’elemento in alto a quello in basso.

Per la risoluzione del seguente problema, abbiamo assegnato all’indice testa il valore iniziale 0. Quindi nel caso in cui la testa sia uguale a zero vuol dire che la pila è vuota.

Nell’operazione Push la variabile testa viene incrementata di 1, invece nell’operazione Pop la variabile testa viene decrementata di 1.

Si poteva anche operare assegnando a testa il valore MAX anzichè zero e ragionare in maniera analoga.

Ecco dunque il semplice algoritmo che realizza le operazioni di inserimento ed estrazione di un elemento in un pila in c. Inoltre implementeremo le operazioni di stampa e svuotamento della pila.

Notate come in questa prima soluzione, sviluppata principalmente a scopo didattico, facciamo uso delle variabili globali.

#include <stdio.h>

#define MAX 3

int testa;
int Pila[MAX];

int menu_scelta(void)
{
  int selezione = 0;
  do
    {
    printf("\n" );
    printf("\n1 -> Aggiungi un dato" );
    printf("\n2 -> Estrai un dato");
    printf("\n3 -> Svuota pila");
    printf("\n4 -> Stampa pila");
    printf("\n5 -> Esci");
    printf("\n" );
    printf("\nEffettua una scelta: " );
    scanf("%d", &selezione );
    }
    while (selezione<1 || selezione>5);
  return selezione;
}

void Push() {
	int n;
	
	if(testa==MAX) 
	         printf("\n -> Pila piena" );
	else {
		 printf("\nInserisci un dato: " );
		 scanf("%d", &n);
		 Pila[testa++]=n;
	}		
}

void Pop() {
	if(testa==0) 
	     printf("\n - Pila vuota" );
	else 
	    printf("%d", Pila[--testa]);	
}

void Clear() {
	testa=0;
	printf("\n -> Pila svuotata" );			
}

void Print() {
	int i;
	if(testa==0) 
	       printf("\n -> Pila vuota" );
	else 
              for(i=testa-1;i>=0;i--)	
                  printf("indice i: %d elemento %d\n", i, Pila[i]);			

}

int main(){
	int scelta;
	
	while((scelta=menu_scelta())!=5){
             switch(scelta){
                   case 1: 
			Push();
                        break;
                   case 2:
			Pop();
               	        break;
                   case 3:
			Clear();
            	        break;
                   case 4: 
			Print();
			break;
	        case 5: 
		        break;
             }
    }             
    return 0;
}

N.B Avremmo anche potuto scrivere nel Push:

	....
        Pila[testa]=n;
        testa++;
        ....

E nel Pop:

         .....
         else {
            testa--;
	    printf("%d", Pila[testa]);
         }
        .....

Questa soluzione, come abbiamo già detto, fa uso delle variabili globali, ma come sappiamo non sempre è bene usarle. Nella prossima lezione implementeremo invece un metodo che non le utilizza. Quindi passeremo i parametri alle funzioni Push(), Pop(), Clear() e Print().

Alcuni link utili

Indice argomenti linguaggio C

La funzione fopen

La funzione fclose

Funzione fprintf

Funzione fscanf

Allocazione dinamica della memoria con malloc

Strutture in C

Typedef struct in C

Esercitazione sulle struct in C

Realizzare un menù di scelta in C

Strutture complesse in C

Come sommare gli elementi della cornice esterna

Come sommare due matrici

Matrice trasposta

Prodotto tra matrici

Ricerca elementi in una matrice

Tavola pitagorica in C

Array multidimensionali

Quick sort in C

Selection sort in C

Merge sort in C

Insertion Sort in C

Stack

Stack

In questa lezione studieremo lo stack (o pila), cioè un elenco di dati avente la caratteristica di permettere l’inserimento di nuovi elementi e l’estrazione degli elementi introdotti ma solo da un’unica estremità.

Un elemento nella pila è inserito con una funzione detta Push, mentre un elemento si estrae con la funzione Pop.

La regola è questa: l’ultimo elemento inserito con Push è il primo ad essere estratto con Pop.

Quindi per questo motivo si parla di struttura LIFO (Last in First Out) ovvero l’ultimo elemento ad entrare è anche il primo ad uscire.

La gestione dello stack si può realizzare o con le linked list o appoggiandosi ad un array visto in “verticale” dove l’inserimento e l’estrazione avvengono sempre dallo stesso lato.

La pila inoltre richiede un indice, che contrassegna la prima casella libera del vettore a partire dalla posizione iniziale.

Questo indice lo chiamiamo testa e quando la pila è vuota il suo valore è zero. Nella posizione indicata dall’indice testa dunque estrarremo o inseriremo i dati con le funzioni Pop e Push.

Rappresentazione in figura

Nella figura ecco un esempio di stack con l’indice testa che indica la prima casella libera e dopo l’inserimento, del numero 5, l’indice testa si sposta di 1.

pila
pila in c

Altre possibili operazioni sono:

Top che restituisce l’elemento superiore dello stack.

isEmpty che restituisce true se lo stack è vuoto, altrimenti false.

isFull che restituisce true se lo stack è pieno, altrimenti vero.

Le operazioni push(), pop(), isEmpty() e top() richiedono tutti tempo O(1), infatti non eseguiamo cicli in nessuna di queste operazioni.

Un tipico esempio di applicazione dello stack si ha nelle Torre di Hanoi, nell’attraversamento degli alberi e in tanti altri algoritmi.

Questa è solo una piccola introduzione sull’uso dello stack, nelle prossime lezioni faremo altri esempi.

Alcuni link utili

Indice argomenti linguaggio C

La funzione fopen

La funzione fclose

Funzione fprintf

Funzione fscanf

Allocazione dinamica della memoria con malloc

Realizzare un menù di scelta in C

Strutture complesse in C

Come sommare gli elementi della cornice esterna

Come sommare due matrici

Matrice trasposta

Prodotto tra matrici

Ricerca elementi in una matrice

Merge sort in C

Insertion Sort in C

ftell

ftell

La funzione ftell in C consente di restituire la posizione corrente del file pointer rispetto all’inizio del file. La posizione corrente è espressa come numero di byte.

La sintassi della funzione ftell in C è dunque la seguente:

long ftell(FILE *fp)

La funzione ftell in C restituisce dunque un intero che è la posizione corrente del puntatore.

FILE *fp è, come nelle altre funzioni, il puntatore a FILE ottenuto dalla precedente chiamata fopen.


Esempio funzione ftell in C

Facciamo adesso un semplice esempio di programma che visualizza la dimensione di un file utilizzando le funzioni fseek ed ftell.

Supponiamo quindi di avere un file di testo di nome alunni.txt che contiene i nomi di alcuni alunni.

Quindi apriamo il file alunni.txt in lettura, con la funzione fopen, e calcoliamo semplicemente la dimensione di questo file utilizzando fseek per spostare il puntatore alla fine del file ed ftell per restituire la dimensione in byte del nostro file.

Ecco dunque il listato dell’esempio con l’uso di ftell in C:

#include <stdio.h>
#include <stdlib.h>
#define N 5

int main() {
	FILE *fp;
	long n;
	
	if((fp=fopen("alunni.txt", "rt"))==NULL) {
		printf("Errore nell'apertura del file'");
		exit(1);
	}
	
	fseek(fp,0L,SEEK_END);
	n=ftell(fp);

	fclose(fp);
	
	printf("Dimensione del file in byte: %ld\n", n);
	
return 0;
	
}

Sono svariati i casi in cui si può utilizzare la funzione ftell in C, infatti si potrebbe ad esempio voler conoscere la posizione di un valore massimo o di un determinato valore a seguito di una ricerca e così via. Nei tutorial che seguiranno vedremo ancora altri esempi d’uso.

Alcuni link utili

Indice argomenti linguaggio C

La funzione fopen

La funzione fclose

Funzione fprintf

Funzione fscanf

Allocazione dinamica della memoria con malloc

Strutture in C

Typedef struct in C

Esercitazione sulle struct in C

Realizzare un menù di scelta in C

Strutture complesse in C

Come sommare gli elementi della cornice esterna

Come sommare due matrici

Matrice trasposta

Prodotto tra matrici

Ricerca elementi in una matrice

Tavola pitagorica in C

Array multidimensionali

Quick sort in C

Selection sort in C

Merge sort in C

Insertion Sort in C

Il linguaggio C

Il linguaggio C

Il linguaggio C è stato sviluppato per la prima volta presso i laboratori Bell di AT&T da Dennis Ritchie nel corso degli anni 1969-1973. Inizialmente, fu creato come evoluzione del linguaggio di programmazione B, anch’esso sviluppato presso i laboratori Bell. Il linguaggio C ha guadagnato rapidamente popolarità grazie alla sua flessibilità e alle sue capacità di programmazione di basso livello.

Caratteristiche Principali del Linguaggio C:

  1. Portabilità:
    • Una delle caratteristiche distintive del linguaggio C è la sua portabilità. Il codice scritto in C può essere eseguito su diverse piattaforme con poche o nessuna modifica. Questa portabilità è stata particolarmente importante nella scrittura di sistemi operativi, dove è essenziale che il codice possa funzionare su una varietà di hardware.
  2. Efficienza e Controllo Diretto sulla Memoria:
    • C offre un controllo diretto sulla memoria del computer, consentendo agli sviluppatori di ottimizzare le prestazioni del codice. Questa caratteristica è utile in situazioni in cui è necessario gestire manualmente l’allocazione e la deallocazione della memoria.
  3. Sintassi Chiara e Concisa:
    • La sintassi del linguaggio C è chiara e concisa, il che rende il codice facile da leggere e scrivere. Questa caratteristica ha contribuito alla sua popolarità e alla sua utilità in una vasta gamma di applicazioni.
  4. Libreria Standard:
    • Il linguaggio C include una libreria standard che fornisce un set di funzioni predefinite che possono essere utilizzate per svolgere una varietà di compiti. Questa libreria standard è stata una delle chiavi del successo del linguaggio.
  5. Puntatori:
    • Il concetto di puntatori è fondamentale nel linguaggio C. I puntatori consentono agli sviluppatori di manipolare direttamente la memoria, offrendo una flessibilità significativa nella gestione dei dati.

Applicazioni del Linguaggio C:

  1. Sistemi Operativi:
    • Il linguaggio C è stato originariamente sviluppato per scrivere il sistema operativo UNIX. Ancora oggi, molti sistemi operativi, inclusi Linux e Windows, sono scritti in gran parte in C.
  2. Sviluppo di Compilatori e Interpreti:
    • A causa della sua efficienza e del controllo diretto sulla memoria, il linguaggio C è spesso utilizzato per scrivere compilatori e interpreti di altri linguaggi di programmazione.
  3. Programmazione di Dispositivi Embedded:
    • La portabilità e l’efficienza del linguaggio C lo rendono una scelta popolare per la programmazione di dispositivi embedded, come microcontrollori e sistemi embedded.
  4. Applicazioni di Sistema e Software di Basso Livello:
    • Il linguaggio C è ampiamente utilizzato per lo sviluppo di applicazioni di sistema, driver di dispositivo e software di basso livello che richiedono un controllo dettagliato sull’hardware.
  5. Sviluppo di Applicazioni Desktop e Software di Rete:
    • Molti programmi desktop e software di rete sono stati sviluppati utilizzando il linguaggio C, grazie alla sua potenza e alla sua capacità di gestire operazioni di basso livello.

Le caratteristiche principali di questo linguaggio sono:

– innanzitutto è case sensitive, ovvero distingue tra lettere maiuscole e minuscole;

– poi è general purpose (multiuso) ovvero può essere impiegato per codificare progetti software di natura diversa;

– il linguaggio C è anche multi-piattaforma;

– è un linguaggio strutturato di tipo imperativo (o procedurale);

– inoltre produce programmi efficienti, infatti è nato per implementare sistemi operativi;

– produce anche codice di dimensioni ridotte, ha infatti una sintassi che si presta alla scrittura di codice compatto.

Struttura di un programma in linguaggio C

In un programma scritto in C vi è una funzione che deve essere sempre presente, che è la funzione main(). Il compilatore infatti inizia l’esecuzione proprio da questa funzione.

La sintassi della funzione main è la seguente:

#include <stdio.h>  // Dichiarazione delle librerie

int main() {  // Funzione principale
    // Dichiarazioni di variabili

    // Istruzioni del programma

    return 0;  // Indica che il programma è stato eseguito con successo
}

Tutto il codice contenuto tra le due parentesi graffe rappresenta il corpo del programma. All’interno del main si possono inserire chiaramente una o più istruzioni, terminanti da una carattere punto e virgola.

Facciamo dunque il primissimo esempio di programma in linguaggio C che dà semplicemente un messaggio di benvenuto all’utente:

#include <stdio.h>

int main() {
    printf("Benvenuti da Coding Creativo");
}

Quindi in questo semplicissimo programma in C abbiamo utilizzato:

  1. #include <stdio.h>:
    • Questa è una direttiva di pre-processore che dice al compilatore di includere il file di intestazione stdio.h. Questo file contiene dichiarazioni necessarie per funzioni di input/output standard come printf e scanf. È una pratica comune includere stdio.h all’inizio di un programma C.
  2. main() { ... }:
    • main è una funzione speciale nel linguaggio C. È la funzione principale che viene eseguita quando il programma viene avviato. Tuttavia, la firma corretta della funzione main è int main(void) o int main(int argc, char *argv[]). Il tuo codice utilizza una forma più antica che implicitamente assume un tipo di ritorno di int.
  3. printf("Benvenuti da Coding Creativo");:
    • printf è una funzione di output standard che consente di stampare testo sullo schermo. Nel tuo caso, sta stampando la stringa “Benvenuti da Coding Creativo”.
  4. Tipo di Ritorno di main:
    • È buona pratica dichiarare il tipo di ritorno di main come int e includere una dichiarazione di ritorno, ad esempio return 0;, per indicare che il programma è stato eseguito con successo.

Nelle prossime lezioni, esploreremo dettagliatamente il concetto di variabili e costanti nel linguaggio C e impareremo come utilizzarle per creare programmi semplici. Approfondiremo la dichiarazione, l’inizializzazione e l’utilizzo di variabili, nonché la corretta gestione di costanti. Questi concetti fondamentali ci forniranno le basi necessarie per realizzare programmi più complessi e versatili. Continuate a seguirmi per imparare a sfruttare appieno il potenziale del linguaggio C.

Alcuni link utili

Indice argomenti sul linguaggio C

Realizzare un menù di scelta in C

Esercizio sulle struct in C

Somma elementi diagonale principale di una matrice

Come sommare gli elementi della cornice esterna

Come sommare due matrici

Matrice trasposta

Inserire dati in una matrice

Tavola pitagorica in C

Array multidimensionali

Programma sui triangoli in C

Media dei numeri in un array

Array con numeri random

Quick sort in C

Compilatore C

Compilatore C

Il compilatore C è necessario per poter compilare ed eseguire i nostri programmi. In questa lezione vi parlerò di Dev C++ per Windows e di GCC per Linux.

Compilatore C quale scaricare?

Ci sono tanti compilatori da poter utilizzare, di seguito ne elenco solo alcuni.

Dev C++

Dev C++ è un IDE gratuito distribuito sotto la licenza GNU ed è scritto in Delphi.

Attenzione però, è un software che può essere eseguito solo su Windows.

Si può scaricare il compilatore Dev C++ dal seguente link: http://www.bloodshed.net.

Una volta installato e poi avviato, si procede sul menù File–> New–> Source File. Si presenta una schermata come quella della figura sotto:

dev c++ compilatore

Questo compilatore C consente di creare anche dei file in linguaggio C++.

Dunque creo, ad esempio, un esercizio che calcola semplicemente il volume di un cubo e lo salvo andando su File–> Save us, avendo cura di scegliere l’estensione giusta nell’opzione salva come.

salvare in linguaggio C

Quindi compiliamo il programma cliccando sul pulsante Compile & Run. Se ci sono errori essi verranno visualizzati.

Di seguito un errore volutamente commesso a scopo dimostrativo:

errori di compilazione

Il compilatore C segnala che manca il ; e dunque con eseguirà il programma.

Se non ci sono errori si aprirà la schermata dove immettere i valori. nell’esempio sotto ho inserito come valore 5 e il programma ha calcolato così il volume pari a 125.

Compilatore C – GCC

Il compilatore GCC è adatto per Linux ed è l’acronimo di GNU Compiler Collection. Non solo permette di compilare codice in C e C++ ma anche in Java, Pascal, Fortran ed altri linguaggi.

Il compilatore GCC non è un preprocessore e consente di individuare meglio gli errori grazie allo Gnu Debbuger.

L’utilizzo del seguente compilatore C è molto semplice ed intuitivo. Potete scaricarlo gratuitamente al seguente link: http://www.gnu.org/software/gcc/releases.html.

Conclusioni

Ci sono tantissimi altri compilatori in C, lascio a voi la ricerca e la valutazione.

Alcuni link utili

Indice argomenti sul linguaggio C

Realizzare un menù di scelta in C

Esercizio sulle struct in C

Somma elementi diagonale principale di una matrice

Come sommare gli elementi della cornice esterna

Come sommare due matrici

Matrice trasposta