Linguaggi | Manuali | Compilatori | Programmi | Script | Software | Linux | Windows | Html
Linguaggi

C
C++
JAVA
PERL
COBOL
PASCAL
MATLAB
FORTRAN77
FORTRAN90

JAVASCRIPT

VISUALBASIC

Sistemi operativi

LINUX
WINDOWS
UNIX
MAC

Software

AUTOCAD
GNUPLOT
OCTAVE
SCILAB

Variabili locali e variabili globali
Tutorial 7
Scritto da Roberto Navigli (roberto.navigli@iol.it)
Game Programming Italia: www.gpi.eden.it

Variabili locali e variabili globali

Le variabili possono essere locali o globali. Una variabile globale è visibile all'interno di tutto il listato mentre una variabile locale è visibile solo all'interno del blocco all'interno del quale essa è dichiarata. Ad esempio:

#include <iostream>
using namespace std;

void main()
{
// a è locale alla funzione main()
int a = 1;

{
// l'intero b è locale a questo blocco
int b = 5;

// ok, b è visibile in questo blocco
cout << b;
}

// errore: b non è visibile
cout << b;
// ok: a è visibile all'interno di main()
cout << a;
}

Vediamo ora la definizione di una variabile globale:

#include <iostream>
using namespace std;

int globale = 5;

void funzione() { globale++; }

void main()
{
globale++;
cout << "Prima: " << globale << endl;
funzione();
cout << "Dopo: " << globale << endl;
}

Compilando quest'ultimo programma si ottiene in output:

Prima: 6
Dopo: 7

È bene evitare il più possibile l'uso delle variabili globali, poiché esse provocano spiacevoli effetti collaterali. Una funzione infatti può fare un uso della stessa variabile
incompatibile con quello che ne fa un'altra funzione. Inoltre spesso l'uso di variabili globali porta forti limitazioni ai programmi che si scrivono. Ad esempio:

#include <iostream>
using namespace std;

// numero di cui calcolare il fattoriale
int numero;

// restituisce numero! (ovvero 1*2*…*n)
int fattoriale()
{
int i, risultato = 1;
for (i = 2; i <= numero; i++) risultato *= i;
return risultato;
}

void main()
{
numero = 5;
cout << "5! = " << fattoriale() << endl;
}

La funzione fattoriale(), dato il fattoriale della variabile intera numero. Dato n, il fattoriale di n (indicato con n!) è:

n! = 1 * 2 * ... * n

Dopo aver compilato ed eseguito il programma si ottiene in output:

5! = 120

Nell'esempio, la variabile numero è globale. Essa viene inizializzata con l'intero 5 nella funzione main. Quindi si chiama la funzione fattoriale che calcola numero!. Il punto è che la funzione non può essere utilizzata per calcolare il fattoriale di qualsiasi intero, ma solo della variabile numero. Usando variabili globali si può ottenere qualcosa di meglio:

#include <iostream>
using namespace std;

// restituisce numero!
int fattoriale(int numero)
{
int i, risultato = 1;
for (i = 2; i <= numero; i++) risultato *= i;
return risultato;
}

void main()
{
cout << "5! + 3! = " << fattoriale(5)+fattoriale(3) << endl;
}

Compilando ed eseguendo il programma, in output si ottiene:

5! + 3! = 126

La versatilità di questa seconda soluzione, che fa uso delle variabili locali, è infinitamente superiore.

Array

Gli array sono tipi di dato "aggregati". Gli array possono avere qualsiasi dimensione. Un array a una dimensione, o vettore, è una sequenza di variabili dello stesso tipo. Ogni variabile che costituisce l'array prende il nome di elemento. Un array si dichiara utilizzando la sintassi che segue:

tipo nome[dimensione];

dove il tipo è un tipo di dato valido in C++, nome è il nome dell'array e dimensione indica il numero di elementi di cui si compone l'array. Ad esempio:

int array[5];

dichiara un array di 5 interi. Per accedere all'i-esimo elemento dell'array è sufficiente scrivere:

array[i]

L'indicizzazione degli elementi parte da 0, quindi in un array di dimensione n gli elementi sono i seguenti:

array[0], array[1], ..., array[n-1]

Essa è a tutti gli effetti una variabile, quindi può essere utilizzata allo stesso modo. Ad esempio:

#include <iostream>
using namespace std;

void main()
{
int numeri[10];

for (int i = 0; i < 10; i++)
{
numeri[i] = i;
cout << numeri[i] << " ";
}
}

In output si ottiene:

0 1 2 3 4 5 6 7 8 9

Il C++ non effettua nessun controllo sui limiti degli array, quindi è possibile richiede l'undicesimo elemento dell'array numeri. Esso rappresenta il contenuto della locazione immediatamente successiva all'ultimo elemento dell'array. Nel migliore dei casi si ottiene un valore insensato. Nel peggiore, si genera un errore nell'applicazione. È sempre bene controllare che il proprio programma non acceda a elementi che non appartengono all'array.

Segue un classico esempio di utilizzo degli array:

#include <iostream>
using namespace std;

void main()
{
int a[10] = { 5, 8, 3, 6, 2, 0, 4, 1, 7, 9 }, min, i = 0;

for (int k = 0; k < 10; k++)
{
// inizializzato a un valore massimo
min = 100;

// preleva il minimo tra i rimanenti 10-k elementi
for (int j = k; j < 10; j++)
if (a[j] < min) { min = a[j]; i = j; }

// scambia l'elemento in k con quello in i
a[i] = a[k];
a[k] = min;

// stampa il k-esimo elemento ordinato
cout << a[k] << " ";
}
}

L'array a è inizializzato specificando i valori tra parentesi graffe. Esso viene ordinato utilizzando l'algoritmo dell'insertion sort. L'algoritmo cerca tra tutti gli elementi quello di valore minimo e lo scambia con il primo, quindi cerca nuovamente il minimo tra gli elementi rimanenti e lo scambio con il secondo e così via.
In output si ottiene il vettore ordinato.

È possibile definire array di qualsiasi dimensione. La sintassi generale è la seguente:

tipo nome[dimensione 1][dimensione 2]…[dimensione n]

Ad esempio:

void main()
{
int tavola[10][10];

// riempie la tavola pitagorica
for (int x = 0; x < 10; x++)
for (int y = 0; y < 10; y++) tavola[y][x] = x*y;
}

Nell'array tavola si ottiene la tavola pitagorica.

Stringhe

L'uso più comune degli array unidimensionali è per le stringhe. In C++, infatti, non esiste un tipo di dato predefinito "stringa". Una stringa è semplicemente un array di caratteri che termina con il carattere ASCII 0. Ad esempio:

#include <iostream>
using namespace std;

void main()
{
char stringa[80];

cout << "Inserisci una stringa: ";
cin >> stringa;

cout << "Hai inserito la stringa: " << stringa << endl;
}

Nell'esempio la stringa è un vettore di 80 caratteri. L'oggetto predefinito cin permette di prelevare in input una stringa e memorizzarla in un array (nell'esempio, l'array omonimo). In output si ottiene:

Inserisci una stringa: pippo
Hai inserito la stringa: pippo

Visualizziamo solo i caratteri pari di una stringa:

#include <iostream>
#include <string.h>
using namespace std;

void main()
{
char stringa[80] = "u-n-a- -s-t-r-i-n-g-a";

for (int k = 0; k < strlen(stringa); k += 2)
cout << stringa[k];
}

Come si può notare, viene incluso il file string.h. Esso contiene le dichiarazioni delle funzioni C di manipolazione delle stringhe. Nell'esempio viene utilizzata la funzione strlen che restituisce la dimensione di una stringa.
Ad ogni iterazione, la variabile k viene incrementata di 2 (anziché di 1) in modo tale che si acceda solo agli elementi pari dell'array di caratteri di cui l'array è costituito.

In output si ottiene:

una stringa

Può tornare utile copiare o modificare le stringhe agevolmente. A questo scopo, le funzioni dichiarate nel file string.h sono di grande utilità. Vediamo subito un esempio:

#include <iostream>
#include <string.h>
using namespace std;

void main()
{
char stringa[80];

// inizializza la stringa con "uno,"
strcpy(stringa, "uno,");
// aggiunge "due" alla stringa "uno,"
strcat(stringa, "due");

if (!strcmp(stringa, "uno"))
cout << "la stringa == \"uno\"";
else if (!strncmp(stringa, "uno", 3))
cout << "la stringa inizia con \"uno\"";
}

All'interno del main si definisce una stringa lunga 80 caratteri. Mediante la funzione strcpy, si copia la stringa "uno," all'interno della stringa. La funzione strcat, quindi, aggiunge "due" in coda alla stringa (che ora contiene "uno,due"). La linea successiva utilizza la funzione strcmp per confrontare la stringa con "uno". Questa funzione restituisce 0 se le due stringhe sono uguali (il che non è vero nell'esempio), un numero diverso da 0 altrimenti. Quindi, poiché il confronto non dà risultato positivo, si utilizza la funzione strncmp, la quale effettua il confronto sui primi n caratteri (dove n è il terzo parametro della funzione, nell'esempio 3). Nell'esempio il confronto va a buon fine, quindi la funzione restituisce 0 e stampa:

la stringa inizia con "uno"

Poiché tutte le stringhe terminano con il carattere ASCII 0, la rappresentazione della stringa in memoria è la seguente:

posizione 0 1 2 3 4 5 6 7 8 9 … 79
carattere u n o , d u e \0 ? ? … ?

La tabella rappresenta la zona di memoria occupata dalla variabile locale stringa. Nella prima posizione (ovvero stringa[0]) si trova il carattere 'u', nella seconda (stringa[1]) il carattere 'n' e così via fino alla posizione 7 in cui si trova il carattere ASCII 0 (che indica la terminazione della stringa). I caratteri dalla posizione 8 alla posizione 79 non sono definiti (indicati con un ?).
È bene fare attenzione al fatto che le funzioni di manipolazione delle stringhe non svolgono alcune controllo sulle dimensioni delle stesse, quindi il programmatore deve incaricarsi di effettuare i dovuti controlli per evitare di incorrere in errori in fase di esecuzione dovuti all'accesso di zone di memoria esterne all'applicazione.

In realtà le funzioni di manipolazione delle stringhe sono un'eredità del linguaggio C. In effetti, la libreria standard del C++ mette a disposizione il tipo di dato string, più sicuro e più semplice da usare. Sfortunatamente la maggior parte del codice scritto finora fa ampio uso delle stringhe così come furono concepite con il linguaggio C ed è per questo che ne faremo largo uso anche in seguito.

Partner

Guida Fortran
Guida Matlab

English Version
Tutorials
Programming
Lavoro
Lavoro in rete
Telelavoro
Webmaster
Webmaster
Xml

Gratis
Autore
G. Ciaburro
Curriculum
Tesi