Sei sulla pagina 1di 22

Editor e ambiente di sviluppo

Per utilizzare il C abbiamo bisogno di un compilatore. Tale strumento software non altro che il tramite tra il nostro codice e il linguaggio macchina del nostro calcolatore, in sintesi esso si occupa della traduzione da alto livello (il codice scritto in C) a quella di basso livello (linguaggio macchina). Esistono molti compilatori per il C per qualsiasi sistema operativo da Windows a Linux. La scelta di uno in particolare ininfluente sui programmi che scriveremo. Siccome tale guida destinata a chi sta muovendo i primi passi nel mondo della programmazione, noi useremo un compilatore freeware il Dev-C++ disponibile sul sito della casa sviluppatrice: http://www.bloodshed.net.
START -> TUTTI I PROGRAMMI -> Blodshed Dev-C++ -> Dev-C++

Una volta lanciato dovrebbe apparire questa schermata:

A questo punto testiamo che tutto funzioni correttamente:


Clicchiamo su File -> Nuovo -> File Sorgente

e scriviamo all'interno della finestra il seguente codice:


#include <stdio.h> #include <stdlib.h> int main() { printf( "Hello, world! \n"); system ("pause"); return 0; }

/* Test per la corretta installazione del compilatore*/

Al momento non ci preoccuperemo di tutto ci che abbiamo scritto ma andremo a cliccare sull'icona compila ed esegui: da sinistra a destra sono: - compila - esegui - compila ed esugui

- ricostruisci - debug Fatto ci, se tutto andato a buon fine, avremo come risultato la seguente schermata:

A questo punto abbiamo tutti gli strumenti per imparare a programmare in C!

Il primo programma
Passiamo ora ad un primo esempio, il codice sotto riportato effettua la moltiplicazione fra due numeri interi.
/* Semplice programma per effettuare la moltiplicazione */ #include<stdio.h> #include<stdlib.h> //dichiarazione di variabili int a, b, c; int main() { // richiesta inserimento primo fattore printf("inserisci un numero intero: "); // acquisizione primo fattore scanf("%d", &a); // richiesta inserimento secondo fattore printf("inserisci un altro numero intero: "); // acquisizione secondo fattore scanf("%d", &b); // assegnazione a c del prodotto fra a e b c = a * b; // stampa del risultato printf("il risultato di %d moltiplicato %d e' %d \n", a, b, c); system("PAUSE"); return 0;

Esaminiamo ora a fondo tale codice: tutto ci che contenuto fra la coppia /* ... */ solo testo di commento - nel nostro caso particolare tutto su una sola linea - quindi tutto ci che scriveremo all'interno di tale coppia sar ignorato dal compilatore. #include <.....> la direttiva di inclusione serve per inserire all'interno del nostro codice le librerie(o header file) di cui abbiamo bisogno. Tali librerie sono scritte, generalmente, dai programmatori del compilatore e contengono funzioni da noi usate come ad esempio la printf(...) la quale specificata all'interno del header file stdio.h. int a,b,c significa che noi vogliamo dichiarare tre variabili rispettivamente a, b e c le quali appartengono al tipo INTERO(int). Gli altri tipi di variabili saranno specificati in seguito nel capitolo 4. // rappresenta il commento per su una sola linea! int main() {....} all'interno di queste parentesi graffe va scritto il cuore del nostro programma, l'int davanti alla parola main sta a significare che tale funzione (main) restituir un parametro intero... sveleremo a breve il significato di tutto ci. printf("text") tale funzione non fa altro che mandare in output sul nostro monitor il testo che c' scritto fra doppi apici. scanf("%d",&a) tutto ci non significa altro che: accogli il dato in input da tastiera e memorizzalo nella variabile a. Il fatto che sia un dato di input specificato dall'uso tra doppi apici del %d, il fatto che debba essere memorizzato in a dato dalla presenza di &a dopo la virgola. c = a * b non fa altro che moltiplicare a * b e porre il risultato in c. Ricorda che in C le associazioni sono sempre da destra verso sinistra ovvero poni quello che c' a destra dell'uguale nella variabile di sinistra. printf("il risultato di %d moltiplicato %d e' %d \n", a, b, c) il significato di questa istruzione pu sembrare a prima vista impossibile da decifrare ma ragionando su quel che abbiamo gi visto il tutto diventa molto semplice: tutto ci che fra doppi apici deve essere stampato a video i %d indicano la presenza di un dato e \n semplicemente il carattere terminatore di riga(il classico INVIO per capirci meglio), la domanda potrebbe essere: "ma cosa sono quelle lettere dopo la virgola?" Nulla di pi facile! sono le variabili i cui valori verranno stampati al posto dei %d in ordine di precedenza. Al primo %d verr sostituito il valore di a, al secondo il valore di b ed al terzo quello di c. system("PAUSE") un altra direttiva al compilatore che indica di sospendere l'esecuzione del programma fino a che non viene premuto un tasto e fa apparire la frase "Premere un tasto per continuare...". return 0 significa che il main stato eseguito correttamente senza errori. Dulcis in fundo vi sarete sicuramente accorti che quasi tutte le righe del codice finisco con un punto e virgola ;... ebbene la mancanza di questi simboli l'errore pi comune di chi si avvicina al C... dunque attenzione!!!! Esso non va messo solo dopo gli #include<...> e dopo una funzione come nel

caso di int main() in quanto dopo di essa vanno le parentesi graffe... a proposito per chi non lo sapesse le parentesi graffe si stampano con: SHIFT+CTRL+ALT+[ oppure ].

Variabili e costanti

Home Didattica Download Servizi News Blog Hosting Forum

Corsi on-line Home > C > Guide > Guida C > Variabili e costanti

Variabili e costanti

0 inShare

Valuta: 1 2 3 4 5 Pubblicato il 01/01/2009 Il C presenta due modi di conservare i dati: le variabili e le costanti. Come facilmente intuibile le variabili sono atte a contenere informazioni che variano nel tempo mentre il valore di una costante resta lo stesso per tutto il tempo dell'esecuzione di un programma. In termini un p pi tecnici una variabile una locazione di memoria a cui stata assegnato un nome con il quale si ha l'accesso al valore della variabile. Possiamo assegnare alle variabili quasi tutti i nomi che ci vengono in mente purch essi NON

inizino per un numero, NON contengano il carattere # e non siano parole riservate dal C (troverete un appendice con tutte le parole riservate del C). E' importante sapere che il C case sensitive ci significa che le variabili pippo, PIPPO e Pippo sono tre differenti variabili quindi fate attenzione a come nominate le vostre variabili cercate di usare una vostra convenzione, ad esempio scrivete sempre le variabili in minuscolo... Abbiamo accennato in precedenza a tipi di variabili, tali tipi vengono usati per definire cosa andremo a memorizzare in una variabile e per effettuare dei controlli sui dati immessi. Ecco tutti i tipi, i loro identificatori e il range entro cui possono variare i valori delle variabili: Tipo di variable Carattere Intero Intero corto Intero lungo Carattere senza segno Intero senza segno Intero senza segno corto Intero senza segno lungo Keyword char int short long unsigned char unsigned int unsigned short unsigned long Bytes Range Occupati 1 2 2 4 1 2 2 4 4 8 -128 a 127 -32768 a 32767 -32768 a 32767 -2.147.483.648 a 2.147.438.647 0 a 255 0 a65535 0 a 65535 0 a 4.294.967.295 1.2E-38 a 3.4E381 2.2E-308 a 1.8E3082

Virgola mobile singola float precisione Virgola mobile doppia double precisione Nota: la E sta per 10 elevato a.

Ora grazie a questa tabella possiamo risparmiare della memoria quando sappiamo che un intero non supera il valore di 127 useremo uno short se sappiamo che esso non negativo gli attribuiremo un tipo unsigned int e cos via. Facciamo ora un esempio di dichiarazione di variabili e vediamo l'uso della funzione sizeof(nomeVariabile) la quale ci restituisce la dimensione della variabile:
#include <stdio.h> #include <stdlib.h> //da qui parte la dichiarazione //delle variabili char a; int b; short c; long d; unsigned char e; unsigned int f; unsigned short g; unsigned long h; float i; double l;

int m = 55; //significa che m assume il valore 55 int main() { printf( "\n a occupa printf( "\n b occupa printf( "\n c occupa printf( "\n d occupa printf( "\n e occupa printf( "\n f occupa printf( "\n g occupa printf( "\n h occupa printf( "\n i occupa printf( "\n l occupa system("PAUSE"); return 0; }

%d %d %d %d %d %d %d %d %d %d

bytes", sizeof(a)); bytes", sizeof(b)); bytes", sizeof(c)); bytes", sizeof(d)); bytes", sizeof(e)); bytes", sizeof(f)); bytes", sizeof(g)); bytes", sizeof(h)); bytes", sizeof(i)); bytes\n", sizeof(l));

Un altro consiglio quello di usare nomi mnemonici per le variabili grazie ai quali facilmente intuibile a cosa serva quella data variabile il significato di int somma sicuramente pi chiaro di int xyz. Passiamo ora alle costanti. Anche esse sono locazioni di memoria dotate di un nome ma al contrario delle variabili esse non sono modificabili. Una costante si pu dichiarare in due modi: facendo precedere al tipo della variabile la keyword const oppure utilizzando la direttiva #define vediamo un altro esempio:
#include <stdio.h> #include <stdlib.h> //definizione costante con direttiva //al preprocessore #define #define piGreco 3.14 float raggio , circ, area; //definizione costante mediante keyword const const float PIGRECO = 3.145; int main() { //richiesta e inserimento raggio //usando il #define printf ("Inserire il raggio: "); scanf("%g", &raggio); //calcola il valore della circonferenza circ = 2 * (piGreco * raggio); //stampa il valore calcolato printf("circonferenza %g \n", circ); //calcola il valore dell'area //usando il const float area = PIGRECO * raggio * raggio; printf("area: %g \n", area); system("PAUSE"); return 0; }

Usare l'uno o l'altro modo non fa molta differenza a livello pratico, essendo questo un corso base li useremo indistintamente.

Per concludere questo capitolo, vediamo quali sono tutti gli specificatori da usare con le funzioni printf() e scanf() a seconda del tipo di variabili usate: Specificatore %c %d (%i) %e (%E) %f %g (%G) %o %p %s %u %x (%X) Tipo variabile char int intero con segno float or double formato esponenziale float or double decimale con segno float or double decimale con segno int valore ottale senza segno pointer indirizzo di un puntatore (vedremo in seguito) array of char stringa di caratteri int decimale senza segno int valore esadecimale senza segno

Operatori e istruzioni condizionali (1a parte)


Un operatore un simbolo mediante il quale si possono compiere determinate operazioni. Gli operatori possono essere suddivisi nelle seguenti categorie: assegnazione, matematici, relazionali e logici. L'operatore di assegnazione l'uguale (=) il suo uso diverso da quello matematico: x = y significa che il valore di y assegnato ad x; nel caso in cui y una funzione allora tale funzione viene calcolata per poi assegnarne il valore ad x. Gli operatori matematici possono essere di due tipi: unari e binari. Gli operatori unari sono cos detti poich essi agiscono su un solo operando. Ve ne sono solo due tipi: Operatore Simbolo Azione Incremento ++ Decremento -Esempio

Incrementa l' operando di uno ++x, x++ Decrementa l' operando di uno --x, x--

In sintesi ++x equivale a x = x + 1 e --y equivale a y = y -1. Inoltre avrete notato che possibile usare tali operatori in maniera prefissa o postfissa il che sta a indicare se l'operando va incrementato prima o dopo l'assegnazione. Nota: per aumentare la leggibilit del vostro codice consigliato non usare frequentemente tali operatori. Gli operatori binari sono invece quelli classici della matematica:

Operatore Addizione Sottrazione Divisione Modulo

Simbolo Azione + / % Somma due operandi Sottrae il secondo operando dal primo Moltiplica due operandi Divide il primo operando per il secondo Restituisce il resto della divisione del primo operando per il secondo.

Esempio x+y x-y x*y x/y x%y

Moltiplicazione *

Gli operatori relazionali vengono usati per "comparare" le espressioni. Un espressione contenente operatori relazionali ammette due tipi di risposte vero (1) o falso (0). Riassumiamo tali operandi in una tabella: Operatore Uguale Maggiore di Minore di Minore o uguale Diverso Simbolo Domanda == > < <= != L' operando 1 uguale all'operando 2? L' operando 1 maggiore dell'operando 2? L' operando 1 minore dell' operando 2? L' operando 1 minore o uguale dell'operando 2? L' operando 1 diverso dall'operando 2? Esempio x == y x>y x<y x <= y x != y

Maggiore o uguale >=

L' operando 1 maggiore o uguale dell'operando 2? x >= y

La seguente tabella invece esplica l'uso di tali operatori relazionali: Expressione 5 == 1 5>1 5 != 1 Come si legge 5 uguale a 1? 5 maggiore di 1? 5 diverso da 1? Valutazione 0 (falso) 1 (vero) 1 (vero)

(5 + 10) == (3 * 5) (5 + 10) uguale a (3 * 5)? 1 (vero) Nota: importante non confondersi con l'operatore di assegnazione (=) e quello di uguaglianza (==)! Passiamo ora alle istruzioni condizionali, tali istruzioni servono per modificare il flusso sequenziale d'esecuzione di un programma, facendo eseguire un'istruzione pi volte oppure nessuna. Il pi semplice dei controlli che possiamo inserire, l'istruzione if: if (espressione) { isruzione1; isruzione2; ................ isruzioneN; }

Le istruzioni da 1...N saranno eseguite se e solo se l'espressione contenuta nell'if risulta vera. Facciamo un esempio:
/*Esempio d'uso dell'istruzione if*/ #include <stdio.h> #include <stdlib.h> int x,y; int main() { //Richiesta inserimento di due interi printf("Inserisci un numero intero: "); scanf("%d",&x); printf("Inserisci un altro numero intero: "); scanf("%d",&y); //stampa a seconda dei valori immessi //la relazione tra i due numeri if ( x == y) printf("x e' uguale a y \n"); if (x > y) printf("x e' maggiore di y \n"); if (x < y) printf("x e' minore di y \n"); system("PAUSE"); return 0; }

In tale codice verr eseguita la printf relativa all'unica espressione relazionale vera contenuta in uno degli if.

Operatori e istruzioni condizionali (2a parte)


Un'estensione dell'if la clausola else essa va interpretata come un oppure modifichiamo l'esempio precedente:
/*Esempio d'uso dell'istruzione if...else if...else*/ #include <stdio.h> #include <stdlib.h> int x,y; int main() { //Richiesta inserimento di due interi printf("Inserisci un numero intero: "); scanf("%d",&x); printf("Inserisci un altro numero intero: "); scanf("%d",&y); //stampa a seconda dei valori immessi //la relazione tra i due numeri

if ( x == y) printf("x e' uguale a y \n"); else if (x > y) printf("x e' maggiore di y \n"); else printf("x e' minore di y \n"); system("PAUSE"); return 0; }

In tal caso il risultato sempre lo stesso di prima ma si ha una maggior velocit nei confronti per verificare la veridicit delle relazioni, inoltre notiamo che l'ultimo else privo di relazione in quanto se x non uguale a y e neppure maggiore sar necessariamente minore, in sintesi quell'ultimo else rappresenta tutti i casi restanti non elencati prima. Per chiarezza facciamo un ultimo esempio sull'uso dell'else: if (et < 18) printf("persona minorenne"); else printf("persona maggiorenne"); Quindi si esegue il ramo dell'else quando risulta falsa la condizione et < 18. Operatori logici. Talvolta potremo aver bisogno di concatenare pi relazioni all'interno della condizione dell'if per fare ci esistono i seguenti operatori logici: Operatore Simbolo Esempio AND OR NOT && || ! exp1 && exp2 exp1 || exp2 !exp1

Tali operatori funzionano nel seguente modo: Espressione Come viene valutata exp1 && exp2 Vero (1) solo se entrambi exp1 e exp2 sono veri; falso (0) altrimenti exp1 || exp2 !exp1 Vero (1) se uno tra exp1 o exp2 vero; false (0) solo se entrambi sono falsi Falso (0) se exp1 vero; vero (1) se exp1 falso

Facciamo un esempio sull'uso degli operatori logici:

/*Esempio d'uso dell'istruzione if...else if...else con condizione composta mediante una AND*/ #include <stdio.h> #include <stdlib.h> int x,y; int main() { //Richiesta inserimento di due interi printf("Inserisci un numero intero: "); scanf("%d",&x); printf("Inserisci un altro numero intero: ");

scanf("%d",&y); //uso di una condizione composta if( x > 0 && y < 0) printf("x ed y hanno segno discorde\n"); system("PAUSE"); return 0; }

Funzioni
Parliamo ora delle funzioni. Esse sono il centro della filosofia della programmazione in C. Abbiamo gi usato alcune funzioni contenute nelle librerie proprie del C, ora impareremo a creare delle funzioni nostre che potremo richiamare quando vorremo fondamentalmente per evitare di dover utilizzare pi volte, all'interno di uno stesso programma, la stessa parte di codice. Una definizione di funzione pu essere la seguente: una parte di codice C dotata di nome che svolge specifiche azioni e opzionalmente restituisce un risultato al programma chiamante. Facciamo un semplice esempio:
/*Una semplice funzione*/ #include <stdio.h> #include <stdlib.h> //prototipo della funzione long cubo(long); long x,y; int main() { //richiesta del numero da elevare //al cubo NOTA %ld indica un long int printf("Inserisci un intero: "); scanf("%ld",&x); //invocazione delle funzione cubo y = cubo(x); printf("Il cubo di %ld e' %ld \n",x,y); system("PAUSE"); return 0; } long cubo(long var) { //calcolo del cubo long var_al_cubo = var * var * var; //indica il valore di ritorno della funzione return var_al_cubo; }

Analiziamo il codice:

long cubo(long) e' il prototipo della funzione serve per far capire al compilatore che useremo tale funzione e per prepararne gli operandi. Tali operandi, nel nostro caso, sono una variabile long di INPUT ed un'altra sempre long di OUTPUT(valore di ritorno). La parola cubo rappresenta la chiave di chiamata della nostra funzione. y = cubo(x) rappresenta la chiamata della funzione e l'assegnazione del valore di ritorno della funzione alla variabile y. long cubo(long var) indica l'inizio della specifica della nostra funzione; inoltre ora specificato il nome che si user per usare la variabile di ingresso, tale nome non dovr essere necessariamente lo stesso quando chiameremo la funzione sar lo stesso compilatore ad effettuare la traduzione x = var. long var_al_cubo = var * var * var calcola il cubo e pone il risultato nella variabile var_al_cubo. return var_al_cubo specifica che il parametro da restituire al chiamante var_al_cubo. Il funzionamento di una chiamata a funzione il seguente: all'atto della chiamata di una funzione vengono impacchettati i dati necessari all'esecuzione in argomenti, a questo punto si eseguono le istruzioni interne alla dichiarazione della funzione, giunti alla clausola return, il flusso di controllo riprende dal punto in cui era stata chiamata la nostra funzione. In sintesi per realiazzare una funzione abbiamo bisogno di due "parti": Prototipo della funzione: tipo_di_ritorno nome_funzione( tipo-arg1,...,tipo-argN); Definizione della funzione: tipo_di_ritorno nome_funzione( tipo-arg1 nome_arg1,...,tipo-argN nome_argN); { Istruzione1; .................. IstruzioneN; [return var_di_ritorno;] } Nota: il tipo di ritorno pu anche essere omesso in quanto una funzione potrebbe non ritornare alcun valore. Per far ci basta dichiarare nel prototipo della funzione al posto del tipo di ritorno la keyword void. Facciamo un 'altro esempio per vedere meglio ci.
/*Una semplice funzione*/ #include <stdio.h> #include <stdlib.h> //prototipo della funzione void stampa(int); int x,y; int main() { printf("Inserisci un intero: "); scanf("%d",&x); printf("Inserisci un secondo intero: ");

scanf("%d",&y); stampa(x); stampa(y); system("PAUSE"); return 0; } void stampa(int var) { printf("valori immessi: %d \n",var); }

Vantaggi dell'uso delle funzioni: E' pi facile scrivere programmi strutturati, a causa della decomposizione di grandi problemi in parti pi piccole, ogni parte verr svolta da una funzione il cui codice e le cui variabili sono isolate dal resto del programma. E' pi facile correggere un programma strutturato in quanto l'errore verr isolato all'interno della funzione e sar pi semplice isolarlo. E' pi semplice riusare il codice gi scritto in quanto facilmente separabile dal resto e facilmente modificabile in modo tale da adeguarlo alle attuali esigenze

Istruzioni di iterazione
Passiamo ora alle istruzioni d'iterazione. Analizzeremo prima il for il quale ci permette di eseguire pi volte una o un insieme di istruzioni, esso deve essere usato nella seguente forma: for (valore iniziale ; condizione incremento) { istruzione1; istruzione2; .................. istruzioneN; } Valore iniziale: indica che valore deve avere la variabile su cui ci appoggiamo per svolgere il nostro ciclo. Condizione: la condizione grazie alla quale si esce dal ciclo e si esegue la prima istruzione esterna al for ci avviene quando tale condizione diviene FALSA. Sbagliare la condizione implica spesso dei Cicli infiniti quindi fate molta attenzione. Incremento: specifica come deve essere incrementata la nostra variabile d'appoggio. Facciamo subito un esempio per comprendere l'utilizzo del for:
/* Un semplice ciclo for */ #include <stdio.h> #include <stdlib.h>

int count; main() { /* Stampa i numeri da 1 a 20 */ for (count = 1; count <= 20; count++) printf("%d\n", count); system("PAUSE"); return 0; }

Notiamo che in questo codice la condizione iniziale data dall'assegnazione del valore 1 alla variabile count, la condizione d'arrestO che count sia uguale al valore 20; infine il passo d'incremento unitario, ovvero ad ogni esecuzione del for la variabile count verr incrementata di uno dal comando count++ (count = count +1). Facciamo ora un altro esempio che contenga anche l'uso degli array (vedi capitolo successivo), tale programma dovr far immettere all'utente al pi 10 numeri oppure interrompere l'inserimento se il numero immesso uguale a 99:
/* Fa inserire all'utente 10 interi oppure interrompe l'inserimento se viene immesso il valore 99*/ #include <stdio.h> #include <stdlib.h> //dichiarazione dell'array dove //conserveremo i valori immessi int value[10]; int i,num=0; int main() { //ciclo for con condizione composta e incremento unitario for (i = 0; i < 10 && num != 99; i++) { printf("Enter a number, 99 to quit: "); scanf("%d", &num); value[i] = num; } system("PAUSE"); return 0; }

Vediamo dunque che la condizione d'uscita composta: ripeti il ciclo sino a che i sia < AND il valore inserito sia diverso da 99 se la condizione d'arresto risulta falsa si entra nelle parentesi del for e alla prima iterazione viene richiesto di inserire un numero; tale numero verr poi memorizzato nella posizione 0 dell'array value alla seconda iterazione "i" varr 1 quindi il valore, sempre se diverso da 99, verr memorizzato alla posizione value[1] e cos via sino a che, o risulta pieno l'array oppure abbiamo inserito il valore 99. E' anche possibile innestare, ovvero mettere uno nell'altro, pi cicli for. Facciamo un esempio in cui vogliamo stampare a video un rettangolo di dimensioni righe * colonne
/* Esempio di due for innestati */ #include <stdio.h> #include <stdlib.h> void draw_box( int, int);

int c, r; int main() { //acquisizione numero righe printf("Inserisci il numero di righe: "); scanf("%d",&r); //acquisizione numero colonne printf("Inserisci il numero di colonne: "); scanf("%d",&c); //invocazione della funzione draw_box( r, c); system("PAUSE"); return 0;

void draw_box( int righe, int colonne ) { int col; //for esterno for ( ; righe > 0; righe--) { //for interno for (col = colonne; col %gt; 0; col--) { printf("X"); } printf("\n"); } }

Nota: l'errore pi comune che si commette quello di separare inizializzazione, condizione e incremento con la virgola (,) anzich con il punto e virgola (;)fate quindi molta attenzione!!! Passiamo ora all'istruzione while la quale ripete un insieme di comandi finch VERA la condizione specificata. Il while ha la seguente sintassi: while ( condizione ) { istruzione1; istruzione2; ................. istruzioneN; } Facciamo subito un semplice esempio:
/* Uso del while */ #include <stdio.h> #include <stlib.h> int count; int main() { /* Come l'esempio del for stampa i numeri da 1 a 20*/ //inizializzazione count = 1; while (count <= 20) {

printf("%d\n", count); //incremento count++; } system("PAUSE"); return 0; }

Avrete notato l'estrema somiglianza con l'istruzione for, infatti tutto ci che scrivete con il while traducibile in un for in effetti preferibile usare il for semplicemente per una questione di immediatezza nella lettura del codice, in quanto nel while va specificato all'interno l'incremento e all'esterno l'inizializzazione, tutto ci nel for scritto in maniera compatta. Non faremo altri esempi sull'uso del while in quanto sarebbero una semplice traduzione. Nota: anche i while sono innestabili basta seguire lo stesso esempio del for. L'ultima istruzione di iterazione che tratteremo il do ... while. La differenza sostanziale con il while normale che l'istruzione del ciclo viene eseguita almeno una volta e continua ad essere eseguita sino a che la condizione risulta essere VERA. La sintassi del do ... while la seguente: do { istruzione1; istruzione2; ................. istruzioneN; } while ( condizione ); Le istruzioni interne ad do vengono eseguite almeno una volta in quanto la condizione posta dopo queste ultime. Logicamente anche questo costrutto sostituibile con un while o con un for esprimendo la condizione d'arresto in modo che essa risulti essere eseguita almeno la prima volta. A causa di ci il do...while risulta essere usato meno frequentemente del semplice while. Un esempio in cui risulta essere utile l'uso dell'istruzione do...while il caso in cui vogliamo creare un menu di selezione per effettuare delle scelte analizziamo il seguente codice:
/* Uso del do...while */ #include <stdio.h> #include <stdlib.h> int get_menu_scelta( void ); int main() { int scelta; scelta = get_menu_scelta(); printf("Hai scelto il menu %d\n", scelta ); system("PAUSE"); return 0; } int get_menu_scelta( void )

{ int selezione = 0; do { printf("\n" ); printf("\n1 - Aggiungi un Record" ); printf("\n2 - Cambia un record"); printf("\n3 - Cancella un record"); printf("\n4 - Esci"); printf("\n" ); printf("\nEffettua una scelta: " ); scanf("%d", &selezione ); } while ( selezione < 1 || selezione > 4 ); return selezione; }

Tale codice non fa altro che stampare le possibili opzioni di scelta e aspettare la scelta dell'utente sino a che esso non digiti un valore valido. Quindi la parte di codice contenuta nel do...while viene eseguita sino a che non risulta falsa la condizione selezione < 1 || selezione > 4 a questo punto si esce dall'istruzione do...while e il valore immesso viene usato per stampare a video printf("Hai scelto il menu %d\n", scelta );.

Gli Array
Un array un insieme ordinato mediante indice di variabili a cui possiamo accedere singolarmente specificando il nome dell'array e l'indice della variabile. Come ogni variabile in C anche gli array devono essere definiti dobbiamo specificare: Il tipo Un nome Il numero di elementi in esso contenuti Facciamo un esempio di dichiararzione: int array[10]; In tale array potremo memorizzare 10 valori e accederemo ad essi nel seguente modo: array[0] = 1; array[1] = 2; array[2] = 3; .................... array[9] = 10; Avrete quindi capito che il primo elemento dell'array non array[1] ma array[0]; Nota: non dichiarate array con dimensione pi grande del necessario per non utilizzare memoria inutilmente. Vi chiederete a questo punto qual l'utilit degli array, essi risultano essere molto comodi quando dobbiamo usare gruppi di variabili, in tal caso invece di utilizzare pi variabili ne dichiariamo un

array e accediamo pi semplicemente ad ogni variabile mediante il suo indice. L'uso degli indici diviene indispensabile se utilizziamo istruzioni di iterazione come il for o il while. Un semplice esempio quello in cui vogliamo memorizzare le nostre spese effettuate in ogni mese, per far ci potremo adoperare 12 variabili di tipo float, ma la gestione di queste ultime risulterebbe lunga e pi intricata, vediamo invece come semplice utilizzare un array di dimensione 13 che chiameremo spese e dove l'indice dell'array corrisponder al mese dell'anno:
/* Uso degli array monodimensionali*/ #include <stdio.h> #include <stdlib.h> /* Dichiarazione di un array e di una variabile di appoggio per il ciclo for*/ float spese[13]; float spesaAnnua = 0; int count; int main() { /* Riempimento dell'array tramite input da tastiera */ for (count = 1; count < 13; count++) { printf("Inserisci le spese per il mese %d: ", count); scanf("%f", &spese[count]); } //stampa il contenuto dell'array for (count = 1; count < 13; count++) { printf("Mese %d = EURO %.2f\n", count, spese[count]); } //spesa annua for (count = 1 ; count < 13; count++) { spesaAnnua = spese[count] + spesaAnnua; } //stampa il valore della spesa annua printf("Spesa annua = EURO %.2f\n", spesaAnnua); system("PAUSE"); return 0; }

Il codice dovrebbe essere di semplice comprensione: iniziamo dalla dichiarazione dell'array, vediamo subito che esso viene dichiarato di dimensione 13 anche se i mesi sono solo 12... facciamo ci solo per poter mantenere una coerenza fra la numerazione normale dei mesi (1 = Gennaio, 2 = Febbraio, etc. ) e l'indice di un array in cui ricordiamo il primo elemento 0 e l'ultimo DIMENSIONE -1. Detto ci analizziamo il primo ciclo for che serve per riempire il nostro array in tal caso la variabile count, ci serve da indice per accedere al valore dell'array, quindi al primo ciclo count varr 1 (poich cos inizializzato) accederemo quindi a spese[1] al secondo giro count verr incrementato, come indicato nel passo d'incremento (count++), accederemo quindi a spese[2] e cos via sino a che non avremo riempito tutto l'array e facendo diventare quindi falsa la condizione del ciclo for in quanto count sar diventato 13.

I restanti for operano nella medesima maniera, quello della stampa semplicemente utilizza count per prelevare il contenuto di spese[count] e mandarlo a video mentre l'ultimo ciclo for non fa altro che sommare alla variabile spesaAnnua (inizializzata a 0) il valore di spese[count]. Dobbiamo ora effettuare una distinzione: quelli trattati sino ad ora sono array monodimensionali simili ai vettori matematici, introduciamo ora gli array bi-dimensionali paragonabili alle matrici matematiche. Tali array servono per memorizzare dati in una specie di tabella avente dimN righe e dimM colonne. Un array del genere viene dichiarato nel seguente modo: matrice[dimN] [dimM]; per accedere ad un elemento dell'array bidimensionale basta al solito specificarne il nome e l'indice che in questo caso una coppia quindi l'elemento in terza riga e quarta colonna sar matrice[ 3 ] [ 4 ]. Per riempire un array bi-dimensionale dobbiamo usare due cicli for innestati: il primo per far scorrere le righe ed il secondo per le colonne, useremo lo stesso trucco per stamparne il contenuto. Facciamo un esempio:
/* Inizializzazione e uso di array bi-dimensionali */ #include <stdio.h> #include <stdlib.h> int matrice[5][3]; int main() { //ciclo d'inserimento for(int i=0; i<5; i++) for(int j=0; j<3; j++) matrice [i][j] = rand(); //ciclo di stampa for( int k=0; k<5; k++) { for(int w=0; w<3; w++) printf("%d \t",matrice[k][w]); printf("\n"); } system("PAUSE"); return 0; }

Il primo ciclo for innestato dovrebbe orami essere chiaro (la funzione rand() viene utilizzata per associare all'elemento di posizione matrice[ i ][ j ] un valore a caso). Vediamo ora il ciclo di stampa, il quale funziona nel seguente modo: il primo for fa scorrere l'indice k che al primo giro varr 0. Mantenendo questo valore si effettua il for innestato il quale assegna a w il valore 0 e stampa il valore contenuto nella posizione matrice[ 0 ][ 0 ]. Nota: \t indica che il valore deve essere seguito da una tabulazione,per avere una stampa pi chiara

Dopo ci w assume il valore w = 1 viene stampato il valore matrice[ 0 ][ 1 ] poi matrice[ 0 ][ 2 ] a questo punto viene posto w = 3 quindi la condizione del for interno non pi verificata. Si esce da tale for e si manda a capo l'output a video tramite il comando \n. Ora k = 0 quindi non possiamo ancora uscire dal primo for quindi k viene posto a 1 dopodich w viene rimesso a 0 cos si stampa il valore di matrice[ 1 ][ 0 ] e cos via sino a quando si stampa l'ultimo valore ovvero matrice[ 4 ][ 2 ].

Le stringhe
Una stringa non niente altro che un insieme di caratteri, ma la loro gestione non per nulla semplice ed immediata in C, molto pi semplice risulta la loro gestione in C++. Proviamo comunque ad imparare le basi dell'uso delle stringhe. Per memorizzare una stringa non esiste un tipo predefinito dobbiamo quindi usare un array di caratteri nella seguente maniera: char string[7]; tale array potr contenere al pi sei caratteri in quanto l'ottavo viene usato per inserirvi un carattere speciale detto carattere terminatore con cui si indica che la stringa terminata, tale carattere \0 Per inizializzare una stringa possiamo operare in due modi: char string[6] = {'F','a','b','i','o','\0'}; char string[6] = "Fabio" Utilizzando il secondo modo sar il compilatore ad aggiungere in automatico il carattere terminatore alla fine della stringa.
#include #include //dichiarazione e inizializzazione di due stringhe char string1[9] = {'M','r','w','c','o','r','s','i','\0'}; char string2[] = "Mrwebmaster"; int main() { printf("%s & %s\n",string2,string1); //modifica string1 printf("Digita la nuova stringa da memorizzare in string 1:"); scanf("%s", &string1); //stampa string 1 printf("String 1 ora vale:"); printf("%s \n",string1); system("PAUSE");

return 0; }

Ricordo che per una trattazione pi completa della gestione delle stringhe si rimanda al Capitolo XX della guida al C++.

Le strutture
Una struttura un contenitore di dati creato a proprio piacimento dal programmatore. In tali strutture possiamo memorizzare un'insieme di dati anche differenti fra loro per tipo. Una struttura viene dichiarata nella seguente maniera: struct nomeStruttura { tipo-var1 nome_var1; tipo-var1 nome_var2; ....... tipo-var1 nome_varN; }istanza Cos facendo creeremo un'istanza di tipo nomeStruttura la quale avr per valori tutti i campi specificati all'interno della struttura. Sar possibile accedere ai singoli campi per modificarli o semplicemente usarli mediante l'operatore . Segue un esempio per chiarire l'uso delle strutture:
#include<stdlib.h> #include<stdio.h> struct Persona { char Nome[30]; char Cognome[30]; char telefono[14]; }; void stampa_Persona(Persona); int main() { Persona p1; //inserimento Nome printf("Inserire i dati della persona: \n"); printf("Nome: "); scanf("%s",p1.Nome); //Inserimento Cognome printf("Cognome: "); scanf("%s",p1.Cognome); //Inserimento numero telefono printf("Telefono formato 081-xxxxxxx: "); scanf("%s",p1.telefono); //Inizializzazzione persona p2

Persona p2 = {"Mario","Rossi","081-7766545"}; stampa_Persona(p1); stampa_Persona(p2); system("PAUSE"); return 0; } void stampa_Persona(Persona x) { printf("%s \n%s \n%s \n\n",x.Nome,x.Cognome,x.telefono); }

Nel codice stata creata una struttura Persona avente tre campi Nome, Cognome e telefono tutti di tipo array di caratteri, vi poi la definizione di alcune variabili che ci serviranno da variabili di appoggio ed infine, prima del main, vi il prototipo della funzione che useremo per stampare a video le varie istanze di Persona. Persona p1; con tale istruzione creiamo una istanza di persona chiamata p1. scanf("%s",p1.Nome); accettiamo in input da tastiera una stringa e tale valore viene posto nel campo nome dell'istanza p1, lo stesso vale per gli scanf successivi solo che memorizzano le stringhe rispettivamente nei campi Cognome e telefono di p1. Persona p2 = {"Mario","Rossi","081-7766545"}; un altro modo di inizializzare una struttura, cos facendo si assegnano dei valori alla struttura p2 gi in fase di compilazione e non in fase di esecuzione come prima. stampa_Persona(p1); la chiamata alla funzione stampa_Persona la quale non fa altro che fare apparire a video i vari campi appartenenti alla persona passata come parametro in questo caso p1. Le strutture si sono evolute col tempo nei cosidetti oggetti, per questo motivo non affronteremo una trattazione pi completa ma si rimanda il lettore alla guida al C++ per avere maggiori dettagli.