Linguaggio C++

Variabili Globali Vs Puntatori

Differenza tra variabile globale e puntatore in C++: perché controllare la visibilità dei dati è fondamentale.

In C++ una variabile può essere globale o locale. Una variabile globale può essere vista e modificata da tutte le funzioni del programma, mentre una variabile locale è visibile solo all interno della funzione che la dichiara. In questa lezione vedremo perché lasciare una variabile visibile a tutto il programma può essere rischioso e come l utilizzo dei puntatori permetta di controllare l accesso ai dati in modo più sicuro.


1️⃣ Cos è una variabile globale

Una variabile globale è dichiarata fuori da tutte le funzioni. Tutte le parti del programma possono leggerla e modificarla senza alcuna limitazione.


int crediti = 500; // variabile globale

void bonus()   { crediti += 100; }
void penalita(){ crediti -= 50;  }

2️⃣ Problemi reali delle variabili globali

  • Difficile fare debug: il valore può cambiare da qualsiasi funzione.
  • Codice fragile: un reset o una modifica inattesa può rompere la logica del programma.
  • Funzioni non riutilizzabili: dipendono dalla globale e non possono essere usate altrove.
  • Perdita di controllo: non puoi decidere quali funzioni possono modificare il dato.
  • Accesso incontrollato: tutte le funzioni possono leggere e scrivere la variabile.

3️⃣ La variabile locale e il puntatore

Una variabile locale vive dentro una funzione (ad esempio il main). Altre funzioni non possono vederla, a meno che tu non gli passi un puntatore.


void bonus(int* p) {
    *p += 100;   // modifica il valore originale
}

int main() {
    int crediti = 500;     // ora è locale
    bonus(&crediti);       // solo la funzione bonus può modificarla
}

4️⃣ Globale vs Puntatore: differenza fondamentale

Variabile Globale Variabile Locale + Puntatore
Visibile da tutto il programma Visibile solo nella funzione proprietaria
Tutte le funzioni possono modificarla Solo chi riceve il puntatore può modificarla
Rende il codice fragile Maggiore sicurezza e controllo
Difficile da debuggare Ogni modifica è tracciabile
LABORATORIO

Simulazione ATM con Operazioni Casuali

In questo laboratorio simulerai il funzionamento di un bancomat. Il programma genererà 50 operazioni casuali (prelievo o versamento), ciascuna con un importo compreso tra 50€ e 500€. Le operazioni verranno memorizzate in un vettore di struct e al termine verrà mostrato il saldo finale e un report completo.

Attenzione: non utilizzare variabili globali. Tutti i dati devono essere gestiti tramite variabili locali e passati alle funzioni tramite puntatori.


1 Preparazione: struttura dell operazione

Ogni operazione deve contenere: tipo (prelievo/versamento), importo utilizzato e saldo dopo l operazione. Crea una struct chiamata Operazione:


struct Operazione {
    string tipo;
    int importo;
    int saldoDopo;
};

Il programma utilizzerà un vettore di 50 elementi di questa struct:


Operazione storico[50];

2 Saldo iniziale e regole del bancomat

Il saldo parte da 1000€. Le operazioni devono rispettare queste regole:

  • Importo compreso tra 50 e 500
  • Se l operazione è un prelievo e il saldo è insufficiente, l operazione deve essere negata
  • Ogni operazione va salvata nel vettore

int saldo = 1000;     // variabile locale

3 Uso di rand()

La funzione rand() genera numeri casuali. Per ottenere un numero da 50 a 500:


int importo = 50 + rand() % 451;  // (500 - 50 + 1) = 451

Per scegliere il tipo di operazione:


int scelta = rand() % 2; // 0 = prelievo, 1 = versamento

4 Funzioni: prelievo e versamento

Crea due funzioni che modificano il saldo tramite puntatore e salvano l operazione effettuata.


void prelievo(int* saldo, int importo, Operazione& op) {
    if (*saldo >= importo) {
        *saldo -= importo;
        op.tipo = "Prelievo";
        op.importo = importo;
        op.saldoDopo = *saldo;
    } else {
        op.tipo = "Prelievo NEGATO";
        op.importo = importo;
        op.saldoDopo = *saldo;
    }
}

void versamento(int* saldo, int importo, Operazione& op) {
    *saldo += importo;
    op.tipo = "Versamento";
    op.importo = importo;
    op.saldoDopo = *saldo;
}

5 Ciclo principale delle 50 operazioni

Ora crea il ciclo che esegue 50 operazioni casuali.


for (int i = 0; i < 50; i++) {

    int importo = 50 + rand() % 451;
    int scelta = rand() % 2; // 0 = prelievo, 1 = versamento

    if (scelta == 0) {
        prelievo(&saldo, importo, storico[i]);
    } else {
        versamento(&saldo, importo, storico[i]);
    }
}

6 Report finale

Stampa tutte le operazioni effettuate e il saldo finale:


for (int i = 0; i < 50; i++) {
    cout << i+1 << ") "
         << storico[i].tipo << " - "
         << storico[i].importo << "€"
         << " | Saldo dopo: " << storico[i].saldoDopo << "€"
         << endl;
}

cout << "\nSALDO FINALE: " << saldo << "€" << endl;